Tuning Ruby's Global Method Cache
shopify.com
shopify.com
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).
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...
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?