ruby/benchmark/vm_ivar_memoize.yml

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

86 строки
1.4 KiB
YAML
Исходник Обычный вид История

vm_getivar: assume the cached shape_id like have a common ancestor When an inline cache misses, it is very likely that the stale shape_id and the current instance shape_id have a close common ancestor. For example if the instance variable is sometimes frozen sometimes not, one of the two shape will be the direct parent of the other. Another pattern that commonly cause IC misses is "memoization", in such case the object will have a "base common shape" and then a number of close descendants. In addition, when we find a common ancestor, we store it in the inline cache instead of the current shape. This help prevent the cache from flip-flopping, ensuring the next lookup will be marginally faster and more generally avoid writing in memory too much. However, now that shapes have an ancestors index, we only check for a few ancestors before falling back to use the index. So overall this change speeds up what is assumed to be the more common case, but makes what is assumed to be the less common case a bit slower. ``` compare-ruby: ruby 3.3.0dev (2023-10-26T05:30:17Z master 701ca070b4) [arm64-darwin22] built-ruby: ruby 3.3.0dev (2023-10-26T09:25:09Z shapes_double_sear.. a723a85235) [arm64-darwin22] warming up...... | |compare-ruby|built-ruby| |:------------------------------------|-----------:|---------:| |vm_ivar_stable_shape | 11.672M| 11.679M| | | -| 1.00x| |vm_ivar_memoize_unstable_shape | 7.551M| 10.506M| | | -| 1.39x| |vm_ivar_memoize_unstable_shape_miss | 11.591M| 11.624M| | | -| 1.00x| |vm_ivar_unstable_undef | 9.037M| 7.981M| | | 1.13x| -| |vm_ivar_divergent_shape | 8.034M| 6.657M| | | 1.21x| -| |vm_ivar_divergent_shape_imbalanced | 10.471M| 9.231M| | | 1.13x| -| ``` Co-Authored-By: John Hawthorn <john@hawthorn.email>
2023-10-26 12:08:05 +03:00
prelude: |
IVARS = 60
class Record
def initialize(offset = false)
@offset = 1 if offset
@first = 0
IVARS.times do |i|
instance_variable_set("@ivar_#{i}", i)
end
end
def first
@first
end
def lazy_set
@lazy_set ||= 123
end
def undef
@undef
end
end
Record.new # Need one alloc to right size
BASE = Record.new
LAZY = Record.new
LAZY.lazy_set
class Miss < Record
@first = 0
IVARS.times do |i|
instance_variable_set("@i_#{i}", i)
end
end
Miss.new # Need one alloc to right size
MISS = Miss.new
DIVERGENT = Record.new(true)
benchmark:
vm_ivar_stable_shape: |
BASE.first
BASE.first
BASE.first
BASE.first
BASE.first
BASE.first
vm_ivar_memoize_unstable_shape: |
BASE.first
LAZY.first
BASE.first
LAZY.first
BASE.first
LAZY.first
vm_ivar_memoize_unstable_shape_miss: |
BASE.first
MISS.first
BASE.first
MISS.first
BASE.first
MISS.first
vm_ivar_unstable_undef: |
BASE.undef
LAZY.undef
BASE.undef
LAZY.undef
BASE.undef
LAZY.undef
vm_ivar_divergent_shape: |
BASE.first
DIVERGENT.first
BASE.first
DIVERGENT.first
BASE.first
DIVERGENT.first
vm_ivar_divergent_shape_imbalanced: |
BASE.first
DIVERGENT.first
DIVERGENT.first
DIVERGENT.first
DIVERGENT.first
DIVERGENT.first