

Tuning Ruby's Global Method Cache - funion
http://www.shopify.com/technology/16777156-tuning-rubys-global-method-cache

======
tenderlove
A fun bit of info, you can get access to the method cache data directly from
Ruby (in MRI) using `RubyVM.stat`. The variables are not really well named,
but here is a test program to demonstrate the behavior:

    
    
        class Foo; end
        
        foo = Foo.new
        
        p RubyVM.stat # => {:global_method_state=>133, :global_constant_state=>804, :class_serial=>5486}
        
        # break a classes method cache. :class_serial will increase
        foo.extend(Module.new { def bar; end })
        
        p RubyVM.stat # => {:global_method_state=>133, :global_constant_state=>804, :class_serial=>5491}
        
        # break Object's method cache. :global_method_state will increase
        class Object
          def omb
          end
        end
        
        p RubyVM.stat # => {:global_method_state=>134, :global_constant_state=>804, :class_serial=>5491}
        
        # break constant cache, :global_constant_state will increase
        Object.send :remove_const, :Foo
        
        p RubyVM.stat # => {:global_method_state=>134, :global_constant_state=>805, :class_serial=>5491}
    

Extending an instance will break the cache for that class. Adding methods to
Object will break the global cache. Removing a constant will break the
constant cache. I think there are other ways to break the caches, but I can't
remember off the top of my head.

Anyway, the point is that you can get access to the information from Ruby, so
I'll use this when testing Rails to ensure we aren't breaking caches. Making a
Rack middleware to output this info might be handy, or adding it to tests
might be a cool project too (like output a warning if a test method breaks the
cache or something).

~~~
sshconnection
Does OpenStruct still break caches?

~~~
gamache
If you're worried about flushing the cache, there's Charlie Somerville's
flush-free OpenStruct:

[https://github.com/charliesome/fast_open_struct](https://github.com/charliesome/fast_open_struct)

------
tmm1
Before the release of 2.1.0, funny_falcon, samsaffron and I developed a patch
that removes the global method cache in favor of a local method cache inside
each class. (This was originally proposed for upstream inclusion in
[https://bugs.ruby-lang.org/issues/9262](https://bugs.ruby-
lang.org/issues/9262)).

The patch has been running in production on GitHub's servers for over a year,
and provides the benefits of a high cache-hit rate without the need for manual
tuning. I recently ported this patch to ruby 2.2 as well and it is available
in this squashed commit:
[https://github.com/github/ruby/commit/bd002fc9fc3c7236395df2...](https://github.com/github/ruby/commit/bd002fc9fc3c7236395df29955984b20188eed06)

~~~
pkmiec
I originally read about this patch here,
[http://samsaffron.com/archive/2014/04/08/ruby-2-1-garbage-
co...](http://samsaffron.com/archive/2014/04/08/ruby-2-1-garbage-collection-
ready-for-production).

There hasn't been any activity on the upstream proposal for almost a year. Has
the core team rejected the idea or is there still hope it will make it into a
future version?

------
legedemon
I learnt more about ruby internals through this post and the comments
thereupon than I had learnt in the whole of last year's sporadic reading.
Thanks everyone for sharing all the links!

