ruby/benchmark/struct_accessor.yml
Jean Boussier f3206cc79b Struct: keep direct reference to IMEMO/fields when space allows
It's not rare for structs to have additional ivars, hence are one
of the most common, if not the most common type in the `gen_fields_tbl`.

This can cause Ractor contention, but even in single ractor mode
means having to do a hash lookup to access the ivars, and increase
GC work.

Instead, unless the struct is perfectly right sized, we can store
a reference to the associated IMEMO/fields object right after the
last struct member.

```
compare-ruby: ruby 3.5.0dev (2025-08-06T12:50:36Z struct-ivar-fields-2 9a30d141a1) +PRISM [arm64-darwin24]
built-ruby: ruby 3.5.0dev (2025-08-06T12:57:59Z struct-ivar-fields-2 2ff3ec237f) +PRISM [arm64-darwin24]
warming up.....

|                      |compare-ruby|built-ruby|
|:---------------------|-----------:|---------:|
|member_reader         |    590.317k|  579.246k|
|                      |       1.02x|         -|
|member_writer         |    543.963k|  527.104k|
|                      |       1.03x|         -|
|member_reader_method  |    213.540k|  213.004k|
|                      |       1.00x|         -|
|member_writer_method  |    192.657k|  191.491k|
|                      |       1.01x|         -|
|ivar_reader           |    403.993k|  569.915k|
|                      |           -|     1.41x|
```

Co-Authored-By: Étienne Barrié <etienne.barrie@gmail.com>
2025-08-06 17:07:49 +02:00

37 lines
669 B
YAML

prelude: |
C = Struct.new(:x) do
def initialize(...)
super
@ivar = 42
end
attr_accessor :ivar
class_eval <<-END
def r
#{'x;'*256}
end
def w
#{'self.x = nil;'*256}
end
def rm
m = method(:x)
#{'m.call;'*256}
end
def wm
m = method(:x=)
#{'m.call(nil);'*256}
end
def r_ivar
#{'ivar;'*256}
end
END
end
C.new(nil) # ensure common shape is known
obj = C.new(nil)
benchmark:
member_reader: "obj.r"
member_writer: "obj.w"
member_reader_method: "obj.rm"
member_writer_method: "obj.wm"
ivar_reader: "obj.r_ivar"