From: ko1@... Date: 2016-05-12T10:12:53+00:00 Subject: [ruby-core:75470] [Ruby trunk Feature#12364] Copy superclass serial number to singleton subclasses for better IMC hits Issue #12364 has been updated by Koichi Sasada. I don't have any objection about this change because it is not big change. Did you measure not micro-benchmarks? ---------------------------------------- Feature #12364: Copy superclass serial number to singleton subclasses for better IMC hits https://bugs.ruby-lang.org/issues/12364#change-58591 * Author: Aaron Patterson * Status: Open * Priority: Normal * Assignee: Koichi Sasada ---------------------------------------- Hi, I've attached a patch that copies the serial number from the superclass to newly created singleton subclasses. For example: ~~~ class Foo def x; end end def bar(v) v.x end a = Foo.new bar(a) a.singleton_class bar(a) ~~~ Today, the IMC for "v.x" would miss on the second call because calling "singleton_class" would mutate the class pointer for the "a" variable and that would result in the "a" variable having a different serial number than the previous call. ## Merits of the patch 1. It's pretty small 2. It looks great in micro benchmarks ;) Given this benchmark: ~~~ class C1 def m; 1; end end o1 = C1.new o2 = C1.new o2.singleton_class i = 0 while i<6_000_000 # benchmark loop 2 o = (i % 2 == 0) ? o1 : o2 o.m; o.m; o.m; o.m; o.m; o.m; o.m; o.m i += 1 end ~~~ Here is trunk Ruby: ~~~ [aaron@TC ruby (trunk)]$ time ./ruby benchmark/bm_vm2_poly_singleton.rb real 0m2.334s user 0m2.308s sys 0m0.015s ~~~ And with my patch applied: ~~~ [aaron@TC ruby (anon_ic)]$ time ./ruby benchmark/bm_vm2_poly_singleton.rb real 0m1.387s user 0m1.360s sys 0m0.014s ~~~ ## Demerits 1. I like to use RubyVM.stat to see if any caches are being broken. This still mutates the global counter, so RubyVM.stat is slightly less helpful (though that data is internal) 2. I don't think it's common to access the singleton class and *not* add methods, so Real World impact may not be very much. I found that RSpec accesses the singleton class but does not add methods: https://github.com/rspec/rspec-core/blob/4504b72a066fe618dd4ccf9425dee349e0f9c560/lib/rspec/core/example.rb#L441 And so does Event Machine: https://github.com/eventmachine/eventmachine/blob/539ae89b1b810f35d2585e4ac239013ac606f60e/lib/em/connection.rb#L49 I haven't been able to check our applications at work yet, but I tried to take some statistics on an RSpec test. I wrote an RSpec test that generated many test cases: https://gist.github.com/tenderlove/9ea76c0274812b477f32e4a542a97f82 Then I logged inline cache hits and misses using a tracepoint that I added: https://github.com/tenderlove/ruby/tree/IC_measure I generated 1000 tests in RSpec, and I can see the cache miss rate drop from a 4.5% to 3%. I tried timing the tests before and after the patch, but I could not prove any significant difference in overall time. I think this patch is small enough that it's worth while to apply, but I don't think it's going to get us much closer to the 3x3 goal. ;-) ---Files-------------------------------- 0001-Copy-the-serial-number-from-the-super-class-to-the-s.patch (1.31 KB) -- https://bugs.ruby-lang.org/ Unsubscribe: