Project

General

Profile

Actions

Feature #12364

closed

Copy superclass serial number to singleton subclasses for better IMC hits

Added by tenderlovemaking (Aaron Patterson) almost 8 years ago. Updated over 7 years ago.

Status:
Closed
Target version:
-
[ruby-core:75425]

Description

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

Updated by ko1 (Koichi Sasada) almost 8 years ago

I don't have any objection about this change because it is not big change.
Did you measure not micro-benchmarks?

Actions #2

Updated by Anonymous over 7 years ago

  • Status changed from Open to Closed

Applied in changeset r56144.


Copy the serial number from the super class to the singleton class

This helps hit inline method caches more frequently. Before this
commit:

[aaron@TC ruby (trunk)]$ time ./ruby -v benchmark/bm_vm2_poly_singleton.rb
ruby 2.4.0dev (2016-09-12 trunk 56141) [x86_64-darwin15]

real  0m3.679s
user  0m3.632s
sys 0m0.022s

After this commit:

[aaron@TC ruby (trunk)]$ time ./ruby -v benchmark/bm_vm2_poly_singleton.rb
ruby 2.4.0dev (2016-09-12 trunk 56141) [x86_64-darwin15]
last_commit=Copy the serial number from the super class to the singleton class

real  0m2.246s
user  0m2.203s
sys 0m0.020s

[Feature #12364]
[ruby-core:75425]

Actions

Also available in: Atom PDF

Like0
Like0Like0