diff options
author | Koichi Sasada <ko1@atdot.net> | 2019-11-29 03:02:44 +0900 |
---|---|---|
committer | Koichi Sasada <ko1@atdot.net> | 2019-11-29 03:11:04 +0900 |
commit | dd723771c118da71aa58bb74537cacaec425542a (patch) | |
tree | 435dd65e4d2e4d6a329c511ab1640cf165dff394 /variable.c | |
parent | b5fbefbf2c14742f6d46ecdf3ce712062dfb1d0a (diff) |
fastpath for ivar read of FL_EXIVAR objects.
vm_getivar() provides fastpath for T_OBJECT by caching an index
of ivar. This patch also provides fastpath for FL_EXIVAR objects.
FL_EXIVAR objects have an each ivar array and index can be cached
as T_OBJECT. To access this ivar array, generic_iv_tbl is exposed
by rb_ivar_generic_ivtbl() (declared in variable.h which is newly
introduced).
Benchmark script:
Benchmark.driver(repeat_count: 3){|x|
x.executable name: 'clean', command: %w'../clean/miniruby'
x.executable name: 'trunk', command: %w'./miniruby'
objs = [Object.new, 'str', {a: 1, b: 2}, [1, 2]]
objs.each.with_index{|obj, i|
rep = obj.inspect
rep = 'Object.new' if /\#/ =~ rep
x.prelude str = %Q{
v#{i} = #{rep}
def v#{i}.foo
@iv # ivar access method (attr_reader)
end
v#{i}.instance_variable_set(:@iv, :iv)
}
puts str
x.report %Q{
v#{i}.foo
}
}
}
Result:
v0.foo # T_OBJECT
clean: 85387141.8 i/s
trunk: 85249373.6 i/s - 1.00x slower
v1.foo # T_STRING
trunk: 57894407.5 i/s
clean: 39957178.6 i/s - 1.45x slower
v2.foo # T_HASH
trunk: 56629413.2 i/s
clean: 39227088.9 i/s - 1.44x slower
v3.foo # T_ARRAY
trunk: 55797530.2 i/s
clean: 38263572.9 i/s - 1.46x slower
Diffstat (limited to 'variable.c')
-rw-r--r-- | variable.c | 13 |
1 files changed, 7 insertions, 6 deletions
diff --git a/variable.c b/variable.c index 46573523b4..d6e2f2a601 100644 --- a/variable.c +++ b/variable.c @@ -23,6 +23,7 @@ #include "debug_counter.h" #include "vm_core.h" #include "transient_heap.h" +#include "variable.h" static struct rb_id_table *rb_global_tbl; static ID autoload, classpath, tmp_classpath; @@ -34,12 +35,6 @@ static VALUE rb_const_search(VALUE klass, ID id, int exclude, int recurse, int v static st_table *generic_iv_tbl; static st_table *generic_iv_tbl_compat; -/* per-object */ -struct gen_ivtbl { - uint32_t numiv; - VALUE ivptr[FLEX_ARY_LEN]; -}; - struct ivar_update { union { st_table *iv_index_tbl; @@ -804,6 +799,12 @@ gen_ivtbl_get(VALUE obj, struct gen_ivtbl **ivtbl) return 0; } +struct st_table * +rb_ivar_generic_ivtbl(void) +{ + return generic_iv_tbl; +} + static VALUE generic_ivar_delete(VALUE obj, ID id, VALUE undef) { |