From: ko1@... Date: 2016-04-12T19:22:00+00:00 Subject: [ruby-core:74906] [Ruby trunk Bug#12274] accessing to instance variable should be fast. Issue #12274 has been updated by Koichi Sasada. Tarui-san suggested another way to optimize and this is my version of that technique (with some refactoring). evaluation result: fps: 19.21335880758348 -> fps: 22.16285461090967 (15% improvement) ``` Index: vm_insnhelper.c =================================================================== --- vm_insnhelper.c (revision 54552) +++ vm_insnhelper.c (working copy) @@ -778,45 +778,47 @@ vm_getivar(VALUE obj, ID id, IC ic, struct rb_call_cache *cc, int is_attr) { #if USE_IC_FOR_IVAR - if (RB_TYPE_P(obj, T_OBJECT)) { - VALUE val = Qundef; - VALUE klass = RBASIC(obj)->klass; + VALUE klass = RBASIC(obj)->klass; + VALUE val; + + if (LIKELY(is_attr ? cc->aux.index > 0 : ic->ic_serial == RCLASS_SERIAL(klass))) { const long len = ROBJECT_NUMIV(obj); const VALUE *const ptr = ROBJECT_IVPTR(obj); + long index = !is_attr ? (long)ic->ic_value.index : (long)(cc->aux.index - 1); - if (LIKELY(is_attr ? cc->aux.index > 0 : ic->ic_serial == RCLASS_SERIAL(klass))) { - long index = !is_attr ? (long)ic->ic_value.index : (long)(cc->aux.index - 1); - - if (index < len) { - val = ptr[index]; - } + if (index < len && (val = ptr[index]) != Qundef) { + return val; } - else { - st_data_t index; - struct st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); + goto undefined; + } + else if (RB_TYPE_P(obj, T_OBJECT)) { + const long len = ROBJECT_NUMIV(obj); + const VALUE *const ptr = ROBJECT_IVPTR(obj); + st_data_t index; + struct st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); + val = Qundef; - if (iv_index_tbl) { - if (st_lookup(iv_index_tbl, id, &index)) { - if ((long)index < len) { - val = ptr[index]; - } - if (!is_attr) { - ic->ic_value.index = index; - ic->ic_serial = RCLASS_SERIAL(klass); - } - else { /* call_info */ - cc->aux.index = (int)index + 1; - } + if (iv_index_tbl) { + if (st_lookup(iv_index_tbl, id, &index)) { + if (!is_attr) { + ic->ic_value.index = index; + ic->ic_serial = RCLASS_SERIAL(klass); } + else { /* call_info */ + cc->aux.index = (int)index + 1; + } + + if ((long)index < len && (val = ptr[index]) != Qundef) { + return val; + } } } - if (UNLIKELY(val == Qundef)) { - if (!is_attr && RTEST(ruby_verbose)) - rb_warning("instance variable %"PRIsVALUE" not initialized", QUOTE_ID(id)); - val = Qnil; + undefined: + if (!is_attr && RTEST(ruby_verbose)) { + rb_warning("instance variable %"PRIsVALUE" not initialized", QUOTE_ID(id)); } - return val; + return Qnil; } #endif /* USE_IC_FOR_IVAR */ if (is_attr) ``` ---------------------------------------- Bug #12274: accessing to instance variable should be fast. https://bugs.ruby-lang.org/issues/12274#change-58030 * Author: Masaya Tarui * Status: Open * Priority: Normal * Assignee: * ruby -v: ruby 2.4.0dev (2016-04-12 trunk 54553) [x86_64-linux] * Backport: 2.1: UNKNOWN, 2.2: UNKNOWN, 2.3: UNKNOWN ---------------------------------------- Currently, accessing to instance variable is quite slower than accessing to local variable. I think accessing to instance variable is basic operation and it should be fast, so tried to improve. patch: https://github.com/tarui/ruby/commit/dd993da80c7ad84340689137bf8b308793595cae On mame's optcarrot benchmark, (https://github.com/mame/optcarrot/) it is 10%(!) faster than trunk. It increases in the maintenance cost a little, but can I commit it? $ ./ruby -v --disable-gems ../../optcarrot/bin/optcarrot --benchmark ../../optcarrot/examples/Lan_Master.nes ruby 2.4.0dev (2016-04-12 trunk 54553) [x86_64-linux] fps: 13.664029283085743 checksum: 59662 $ ./ruby -v --disable-gems ../../optcarrot/bin/optcarrot --benchmark ../../optcarrot/examples/Lan_Master.nes ruby 2.4.0dev (2016-04-12 fast-ivar-access 54553) [x86_64-linux] fps: 15.120651593726231 checksum: 59662 -- https://bugs.ruby-lang.org/ Unsubscribe: