Live data from Hacker News

Tuning Ruby's Global Method Cache

shopify.com

1–9 of 9 posts

Re: Tuning Ruby's Global Method Cache

#2
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).

Re: Tuning Ruby's Global Method Cache

#3

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 { d…

Does OpenStruct still break caches?

Re: Tuning Ruby's Global Method Cache

#4

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 { d…

Does OpenStruct still break caches?

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

https://github.com/charliesome/fast_open_struct

Re: Tuning Ruby's Global Method Cache

#5

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 { d…

Thanks! The idea of adding this to tests or a middleware is very good :)

Re: Tuning Ruby's Global Method Cache

#6
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).

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...

Re: Tuning Ruby's Global Method Cache

#7

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 { d…

The https://github.com/simeonwillbanks/busted gem provides some nice helpers around RubyVM.stat for finding cache invalidations. It can also take advantage of the dtrace/systemtap probes that shipped with ruby 2.1 (http://tmm1.net/ruby21-method-cache) which can be used as an alternative to the ftrace technique described in the blog post.

Re: Tuning Ruby's Global Method Cache

#8
post #6

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 ). 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 manua…

I originally read about this patch here, http://samsaffron.com/archive/2014/04/08/ruby-2-1-garbage-co....

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?