tuning ivar set
* make rb_init_iv_list() simple * introduce vm_setivar_slowpath() for cache miss cases ../clean/miniruby is 647ee6f091. Calculating ------------------------------------- ./miniruby ../clean/miniruby ../ruby_2_7/miniruby vm_ivar_init 7.388M 6.814M 5.771M i/s - 30.000M times in 4.060420s 4.402534s 5.198781s vm_ivar_init_subclass 2.158M 2.147M 1.974M i/s - 3.000M times in 1.390328s 1.397587s 1.519951s vm_ivar_set 128.607M 97.931M 140.668M i/s - 30.000M times in 0.233269s 0.306338s 0.213268s vm_ivar 144.315M 151.722M 117.734M i/s - 30.000M times in 0.207879s 0.197730s 0.254811s Comparison: vm_ivar_init ./miniruby: 7388398.8 i/s ../clean/miniruby: 6814257.1 i/s - 1.08x slower ../ruby_2_7/miniruby: 5770583.9 i/s - 1.28x slower vm_ivar_init_subclass ./miniruby: 2157763.6 i/s ../clean/miniruby: 2146557.0 i/s - 1.01x slower ../ruby_2_7/miniruby: 1973747.9 i/s - 1.09x slower vm_ivar_set ../ruby_2_7/miniruby: 140668063.8 i/s ./miniruby: 128606912.1 i/s - 1.09x slower ../clean/miniruby: 97931027.8 i/s - 1.44x slower vm_ivar ../clean/miniruby: 151722121.9 i/s ./miniruby: 144314526.5 i/s - 1.05x slower ../ruby_2_7/miniruby: 117734305.5 i/s - 1.29x slower
This commit is contained in:
parent
ad8e82f708
commit
5499651ee7
Notes:
git
2025-06-06 00:31:58 +00:00
@ -52,7 +52,7 @@ VALUE rb_gvar_get(ID);
|
|||||||
VALUE rb_gvar_set(ID, VALUE);
|
VALUE rb_gvar_set(ID, VALUE);
|
||||||
VALUE rb_gvar_defined(ID);
|
VALUE rb_gvar_defined(ID);
|
||||||
void rb_const_warn_if_deprecated(const rb_const_entry_t *, VALUE, ID);
|
void rb_const_warn_if_deprecated(const rb_const_entry_t *, VALUE, ID);
|
||||||
void rb_init_iv_list(VALUE obj, uint32_t len, uint32_t newsize, st_table * index_tbl);
|
void rb_init_iv_list(VALUE obj);
|
||||||
MJIT_SYMBOL_EXPORT_END
|
MJIT_SYMBOL_EXPORT_END
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
|
15
variable.c
15
variable.c
@ -1413,8 +1413,8 @@ rb_obj_transient_heap_evacuate(VALUE obj, int promote)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void
|
static void
|
||||||
rb_init_iv_list(VALUE obj, uint32_t len, uint32_t newsize, st_table * index_tbl)
|
init_iv_list(VALUE obj, uint32_t len, uint32_t newsize, st_table *index_tbl)
|
||||||
{
|
{
|
||||||
VALUE *ptr = ROBJECT_IVPTR(obj);
|
VALUE *ptr = ROBJECT_IVPTR(obj);
|
||||||
VALUE *newptr;
|
VALUE *newptr;
|
||||||
@ -1435,6 +1435,15 @@ rb_init_iv_list(VALUE obj, uint32_t len, uint32_t newsize, st_table * index_tbl)
|
|||||||
ROBJECT(obj)->as.heap.iv_index_tbl = index_tbl;
|
ROBJECT(obj)->as.heap.iv_index_tbl = index_tbl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_init_iv_list(VALUE obj)
|
||||||
|
{
|
||||||
|
st_table *index_tbl = ROBJECT_IV_INDEX_TBL(obj);
|
||||||
|
uint32_t newsize = (uint32_t)index_tbl->num_entries;
|
||||||
|
uint32_t len = ROBJECT_NUMIV(obj);
|
||||||
|
init_iv_list(obj, len, newsize, index_tbl);
|
||||||
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
obj_ivar_set(VALUE obj, ID id, VALUE val)
|
obj_ivar_set(VALUE obj, ID id, VALUE val)
|
||||||
{
|
{
|
||||||
@ -1453,7 +1462,7 @@ obj_ivar_set(VALUE obj, ID id, VALUE val)
|
|||||||
len = ROBJECT_NUMIV(obj);
|
len = ROBJECT_NUMIV(obj);
|
||||||
if (len <= ivup.index) {
|
if (len <= ivup.index) {
|
||||||
uint32_t newsize = iv_index_tbl_newsize(&ivup);
|
uint32_t newsize = iv_index_tbl_newsize(&ivup);
|
||||||
rb_init_iv_list(obj, len, newsize, ivup.u.iv_index_tbl);
|
init_iv_list(obj, len, newsize, ivup.u.iv_index_tbl);
|
||||||
}
|
}
|
||||||
RB_OBJ_WRITE(obj, &ROBJECT_IVPTR(obj)[ivup.index], val);
|
RB_OBJ_WRITE(obj, &ROBJECT_IVPTR(obj)[ivup.index], val);
|
||||||
|
|
||||||
|
@ -1190,34 +1190,16 @@ vm_getivar(VALUE obj, ID id, const rb_iseq_t *iseq, IVC ic, const struct rb_call
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline VALUE
|
|
||||||
vm_setivar(VALUE obj, ID id, VALUE val, const rb_iseq_t *iseq, IVC ic, const struct rb_callcache *cc, int is_attr)
|
NOINLINE(static VALUE vm_setivar_slowpath(VALUE obj, ID id, VALUE val, const rb_iseq_t *iseq, IVC ic, const struct rb_callcache *cc, int is_attr));
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
vm_setivar_slowpath(VALUE obj, ID id, VALUE val, const rb_iseq_t *iseq, IVC ic, const struct rb_callcache *cc, int is_attr)
|
||||||
{
|
{
|
||||||
#if OPT_IC_FOR_IVAR
|
|
||||||
rb_check_frozen_internal(obj);
|
rb_check_frozen_internal(obj);
|
||||||
|
|
||||||
if (LIKELY(RB_TYPE_P(obj, T_OBJECT))) {
|
#if OPT_IC_FOR_IVAR
|
||||||
VALUE klass = RBASIC(obj)->klass;
|
if (RB_TYPE_P(obj, T_OBJECT)) {
|
||||||
uint32_t index;
|
|
||||||
|
|
||||||
VM_ASSERT(!rb_ractor_shareable_p(obj));
|
|
||||||
|
|
||||||
if (LIKELY(
|
|
||||||
(!is_attr && RB_DEBUG_COUNTER_INC_UNLESS(ivar_set_ic_miss_serial, ic->entry && ic->entry->class_serial == RCLASS_SERIAL(klass))) ||
|
|
||||||
( is_attr && RB_DEBUG_COUNTER_INC_UNLESS(ivar_set_ic_miss_unset, vm_cc_attr_index(cc) > 0)))) {
|
|
||||||
VALUE *ptr = ROBJECT_IVPTR(obj);
|
|
||||||
index = !is_attr ? ic->entry->index : vm_cc_attr_index(cc)-1;
|
|
||||||
|
|
||||||
if (index >= ROBJECT_NUMIV(obj)) {
|
|
||||||
st_table * iv_idx_tbl = ROBJECT_IV_INDEX_TBL(obj);
|
|
||||||
rb_init_iv_list(obj, ROBJECT_NUMIV(obj), (uint32_t)iv_idx_tbl->num_entries, iv_idx_tbl);
|
|
||||||
ptr = ROBJECT_IVPTR(obj);
|
|
||||||
}
|
|
||||||
RB_OBJ_WRITE(obj, &ptr[index], val);
|
|
||||||
RB_DEBUG_COUNTER_INC(ivar_set_ic_hit);
|
|
||||||
return val; /* inline cache hit */
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
struct st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
|
struct st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
|
||||||
struct rb_iv_index_tbl_entry *ent;
|
struct rb_iv_index_tbl_entry *ent;
|
||||||
|
|
||||||
@ -1233,27 +1215,57 @@ vm_setivar(VALUE obj, ID id, VALUE val, const rb_iseq_t *iseq, IVC ic, const str
|
|||||||
vm_cc_attr_index_set(cc, (int)(ent->index + 1));
|
vm_cc_attr_index_set(cc, (int)(ent->index + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
index = ent->index;
|
uint32_t index = ent->index;
|
||||||
|
|
||||||
VALUE *ptr = ROBJECT_IVPTR(obj);
|
if (UNLIKELY(index >= ROBJECT_NUMIV(obj))) {
|
||||||
if (index >= ROBJECT_NUMIV(obj)) {
|
rb_init_iv_list(obj);
|
||||||
rb_init_iv_list(obj, ROBJECT_NUMIV(obj), (uint32_t)iv_index_tbl->num_entries, iv_index_tbl);
|
|
||||||
ptr = ROBJECT_IVPTR(obj);
|
|
||||||
}
|
}
|
||||||
|
VALUE *ptr = ROBJECT_IVPTR(obj);
|
||||||
RB_OBJ_WRITE(obj, &ptr[index], val);
|
RB_OBJ_WRITE(obj, &ptr[index], val);
|
||||||
RB_DEBUG_COUNTER_INC(ivar_set_ic_miss_iv_hit);
|
RB_DEBUG_COUNTER_INC(ivar_set_ic_miss_iv_hit);
|
||||||
|
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
/* fall through */
|
}
|
||||||
|
#endif
|
||||||
|
RB_DEBUG_COUNTER_INC(ivar_set_ic_miss);
|
||||||
|
return rb_ivar_set(obj, id, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline VALUE
|
||||||
|
vm_setivar(VALUE obj, ID id, VALUE val, const rb_iseq_t *iseq, IVC ic, const struct rb_callcache *cc, int is_attr)
|
||||||
|
{
|
||||||
|
#if OPT_IC_FOR_IVAR
|
||||||
|
if (LIKELY(RB_TYPE_P(obj, T_OBJECT)) &&
|
||||||
|
LIKELY(!RB_OBJ_FROZEN_RAW(obj))) {
|
||||||
|
|
||||||
|
VM_ASSERT(!rb_ractor_shareable_p(obj));
|
||||||
|
|
||||||
|
if (LIKELY(
|
||||||
|
(!is_attr && RB_DEBUG_COUNTER_INC_UNLESS(ivar_set_ic_miss_serial, ic->entry && ic->entry->class_serial == RCLASS_SERIAL(RBASIC(obj)->klass))) ||
|
||||||
|
( is_attr && RB_DEBUG_COUNTER_INC_UNLESS(ivar_set_ic_miss_unset, vm_cc_attr_index(cc) > 0)))) {
|
||||||
|
uint32_t index = !is_attr ? ic->entry->index : vm_cc_attr_index(cc)-1;
|
||||||
|
|
||||||
|
if (UNLIKELY(index >= ROBJECT_NUMIV(obj))) {
|
||||||
|
rb_init_iv_list(obj);
|
||||||
|
}
|
||||||
|
VALUE *ptr = ROBJECT_IVPTR(obj);
|
||||||
|
RB_OBJ_WRITE(obj, &ptr[index], val);
|
||||||
|
RB_DEBUG_COUNTER_INC(ivar_set_ic_hit);
|
||||||
|
return val; /* inline cache hit */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
RB_DEBUG_COUNTER_INC(ivar_set_ic_miss_noobject);
|
RB_DEBUG_COUNTER_INC(ivar_set_ic_miss_noobject);
|
||||||
}
|
}
|
||||||
#endif /* OPT_IC_FOR_IVAR */
|
#endif /* OPT_IC_FOR_IVAR */
|
||||||
RB_DEBUG_COUNTER_INC(ivar_set_ic_miss);
|
return vm_setivar_slowpath(obj, id, val, iseq, ic, cc, is_attr);
|
||||||
return rb_ivar_set(obj, id, val);
|
}
|
||||||
|
|
||||||
|
VALUE
|
||||||
|
rb_vm_setivar(VALUE obj, ID id, VALUE val, const rb_iseq_t *iseq, IVC ic)
|
||||||
|
{
|
||||||
|
return vm_setivar(obj, id, val, iseq, ic, NULL, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline VALUE
|
static inline VALUE
|
||||||
|
Loading…
x
Reference in New Issue
Block a user