diff options
Diffstat (limited to 'debug_counter.h')
| -rw-r--r-- | debug_counter.h | 299 |
1 files changed, 222 insertions, 77 deletions
diff --git a/debug_counter.h b/debug_counter.h index b390563a90..721ff9d1b8 100644 --- a/debug_counter.h +++ b/debug_counter.h @@ -14,28 +14,99 @@ #ifdef RB_DEBUG_COUNTER +// method cache (IMC: inline method cache) +RB_DEBUG_COUNTER(mc_inline_hit) // IMC hit +RB_DEBUG_COUNTER(mc_inline_miss_klass) // IMC miss by different class +RB_DEBUG_COUNTER(mc_inline_miss_invalidated) // IMC miss by invalidated ME +RB_DEBUG_COUNTER(mc_inline_miss_empty) // IMC miss because prev is empty slot +RB_DEBUG_COUNTER(mc_inline_miss_same_cc) // IMC miss, but same CC +RB_DEBUG_COUNTER(mc_inline_miss_same_cme) // IMC miss, but same CME +RB_DEBUG_COUNTER(mc_inline_miss_same_def) // IMC miss, but same definition +RB_DEBUG_COUNTER(mc_inline_miss_diff) // IMC miss, different methods + +RB_DEBUG_COUNTER(cvar_write_inline_hit) // cvar cache hit on write +RB_DEBUG_COUNTER(cvar_read_inline_hit) // cvar cache hit on read +RB_DEBUG_COUNTER(cvar_inline_miss) // miss inline cache +RB_DEBUG_COUNTER(cvar_class_invalidate) // invalidate cvar cache when define a cvar that's defined on a subclass +RB_DEBUG_COUNTER(cvar_include_invalidate) // invalidate cvar cache on module include or prepend + +RB_DEBUG_COUNTER(mc_cme_complement) // number of acquiring complement CME +RB_DEBUG_COUNTER(mc_cme_complement_hit) // number of cache hit for complemented CME + +RB_DEBUG_COUNTER(mc_search) // count for method lookup in class tree +RB_DEBUG_COUNTER(mc_search_notfound) // method lookup, but not found +RB_DEBUG_COUNTER(mc_search_super) // total traversed classes + +// callinfo +RB_DEBUG_COUNTER(ci_packed) // number of packed CI +RB_DEBUG_COUNTER(ci_kw) // non-packed CI w/ keywords +RB_DEBUG_COUNTER(ci_nokw) // non-packed CI w/o keywords +RB_DEBUG_COUNTER(ci_runtime) // creating temporary CI + +// callcache +RB_DEBUG_COUNTER(cc_new) // number of CC +RB_DEBUG_COUNTER(cc_temp) // dummy CC (stack-allocated) +RB_DEBUG_COUNTER(cc_found_in_ccs) // count for CC lookup success in CCS +RB_DEBUG_COUNTER(cc_not_found_in_ccs) // count for CC lookup success in CCS + +RB_DEBUG_COUNTER(cc_ent_invalidate) // count for invalidating cc (cc->klass = Qundef) +RB_DEBUG_COUNTER(cc_cme_invalidate) // count for invalidating CME + +RB_DEBUG_COUNTER(cc_invalidate_leaf) // count for invalidating klass if klass has no-subclasses +RB_DEBUG_COUNTER(cc_invalidate_leaf_ccs) // corresponding CCS +RB_DEBUG_COUNTER(cc_invalidate_leaf_callable) // complimented cache (no-subclasses) +RB_DEBUG_COUNTER(cc_invalidate_tree) // count for invalidating klass if klass has subclasses +RB_DEBUG_COUNTER(cc_invalidate_tree_cme) // cme if cme is found in this class or superclasses +RB_DEBUG_COUNTER(cc_invalidate_tree_callable) // complimented cache (subclasses) +RB_DEBUG_COUNTER(cc_invalidate_negative) // count for invalidating negative cache + +RB_DEBUG_COUNTER(ccs_free) // count for free'ing ccs +RB_DEBUG_COUNTER(ccs_maxlen) // maximum length of ccs +RB_DEBUG_COUNTER(ccs_found) // count for finding corresponding ccs on method lookup +RB_DEBUG_COUNTER(ccs_not_found) // count for not found corresponding ccs on method lookup + +// vm_eval.c +RB_DEBUG_COUNTER(call0_public) +RB_DEBUG_COUNTER(call0_other) +RB_DEBUG_COUNTER(gccct_hit) +RB_DEBUG_COUNTER(gccct_miss) +RB_DEBUG_COUNTER(gccct_null) + +// iseq +RB_DEBUG_COUNTER(iseq_num) // number of total created iseq +RB_DEBUG_COUNTER(iseq_cd_num) // number of total created cd (call_data) + /* - * method cache (mc) counts. - * - * * mc_inline_hit/miss: inline mc hit/miss counts (VM send insn) - * * mc_global_hit/miss: global method cache hit/miss counts - * two types: (1) inline cache miss (VM send insn) - * (2) called from C (rb_funcall). - * * mc_global_state_miss: inline mc miss by global_state miss. - * * mc_class_serial_miss: ... by mc_class_serial_miss - * * mc_cme_complement: cme complement counts. - * * mc_cme_complement_hit: cme cache hit counts. - * * mc_search_super: search_method() call counts. + * call cache fastpath usage */ -RB_DEBUG_COUNTER(mc_inline_hit) -RB_DEBUG_COUNTER(mc_inline_miss) -RB_DEBUG_COUNTER(mc_global_hit) -RB_DEBUG_COUNTER(mc_global_miss) -RB_DEBUG_COUNTER(mc_global_state_miss) -RB_DEBUG_COUNTER(mc_class_serial_miss) -RB_DEBUG_COUNTER(mc_cme_complement) -RB_DEBUG_COUNTER(mc_cme_complement_hit) -RB_DEBUG_COUNTER(mc_search_super) +RB_DEBUG_COUNTER(ccf_general) +RB_DEBUG_COUNTER(ccf_iseq_setup) +RB_DEBUG_COUNTER(ccf_iseq_setup_0start) +RB_DEBUG_COUNTER(ccf_iseq_setup_tailcall_0start) +RB_DEBUG_COUNTER(ccf_iseq_fix) /* several functions created with tool/mk_call_iseq_optimized.rb */ +RB_DEBUG_COUNTER(ccf_iseq_opt) /* has_opt == TRUE (has optional parameters), but other flags are FALSE */ +RB_DEBUG_COUNTER(ccf_iseq_kw1) /* vm_call_iseq_setup_kwparm_kwarg() */ +RB_DEBUG_COUNTER(ccf_iseq_kw2) /* vm_call_iseq_setup_kwparm_nokwarg() */ +RB_DEBUG_COUNTER(ccf_cfunc) +RB_DEBUG_COUNTER(ccf_cfunc_with_frame) +RB_DEBUG_COUNTER(ccf_ivar) /* attr_reader */ +RB_DEBUG_COUNTER(ccf_attrset) /* attr_writer */ +RB_DEBUG_COUNTER(ccf_method_missing) +RB_DEBUG_COUNTER(ccf_zsuper) +RB_DEBUG_COUNTER(ccf_bmethod) +RB_DEBUG_COUNTER(ccf_opt_send) +RB_DEBUG_COUNTER(ccf_opt_call) +RB_DEBUG_COUNTER(ccf_opt_block_call) +RB_DEBUG_COUNTER(ccf_opt_struct_aref) +RB_DEBUG_COUNTER(ccf_opt_struct_aset) +RB_DEBUG_COUNTER(ccf_super_method) +RB_DEBUG_COUNTER(ccf_cfunc_other) +RB_DEBUG_COUNTER(ccf_cfunc_only_splat) +RB_DEBUG_COUNTER(ccf_cfunc_only_splat_kw) +RB_DEBUG_COUNTER(ccf_iseq_bmethod) +RB_DEBUG_COUNTER(ccf_noniseq_bmethod) +RB_DEBUG_COUNTER(ccf_opt_send_complex) +RB_DEBUG_COUNTER(ccf_opt_send_simple) /* * control frame push counts. @@ -63,30 +134,22 @@ RB_DEBUG_COUNTER(frame_R2C) RB_DEBUG_COUNTER(frame_C2C) RB_DEBUG_COUNTER(frame_C2R) -/* instance variable counts - * - * * ivar_get_ic_hit/miss: ivar_get inline cache (ic) hit/miss counts (VM insn) - * * ivar_get_ic_miss_serial: ivar_get ic miss reason by serial (VM insn) - * * ivar_get_ic_miss_unset: ... by unset (VM insn) - * * ivar_get_ic_miss_noobject: ... by "not T_OBJECT" (VM insn) - * * ivar_set_...: same counts with ivar_set (VM insn) - * * ivar_get/set_base: call counts of "rb_ivar_get/set()". - * because of (1) ic miss. - * (2) direct call by C extensions. - */ -RB_DEBUG_COUNTER(ivar_get_ic_hit) -RB_DEBUG_COUNTER(ivar_get_ic_miss) -RB_DEBUG_COUNTER(ivar_get_ic_miss_serial) -RB_DEBUG_COUNTER(ivar_get_ic_miss_unset) -RB_DEBUG_COUNTER(ivar_get_ic_miss_noobject) -RB_DEBUG_COUNTER(ivar_set_ic_hit) -RB_DEBUG_COUNTER(ivar_set_ic_miss) -RB_DEBUG_COUNTER(ivar_set_ic_miss_serial) -RB_DEBUG_COUNTER(ivar_set_ic_miss_unset) -RB_DEBUG_COUNTER(ivar_set_ic_miss_oorange) -RB_DEBUG_COUNTER(ivar_set_ic_miss_noobject) -RB_DEBUG_COUNTER(ivar_get_base) -RB_DEBUG_COUNTER(ivar_set_base) +/* instance variable counts */ +RB_DEBUG_COUNTER(ivar_get_obj_hit) // Only T_OBJECT hits +RB_DEBUG_COUNTER(ivar_get_obj_miss) // Only T_OBJECT misses +RB_DEBUG_COUNTER(ivar_get_ic_hit) // All hits +RB_DEBUG_COUNTER(ivar_get_ic_miss) // All misses +RB_DEBUG_COUNTER(ivar_set_ic_hit) // All hits +RB_DEBUG_COUNTER(ivar_set_obj_hit) // Only T_OBJECT hits +RB_DEBUG_COUNTER(ivar_set_obj_miss) // Only T_OBJECT misses +RB_DEBUG_COUNTER(ivar_set_ic_miss) // All misses +RB_DEBUG_COUNTER(ivar_set_ic_miss_noobject) // Miss because non T_OBJECT +RB_DEBUG_COUNTER(ivar_get_base) // Calls to `rb_ivar_get` (very slow path) +RB_DEBUG_COUNTER(ivar_set_base) // Calls to `ivar_set` (very slow path) +RB_DEBUG_COUNTER(ivar_get_ic_miss_set) // Misses on IV reads where the cache was wrong +RB_DEBUG_COUNTER(ivar_get_cc_miss_set) // Misses on attr_reader where the cache was wrong +RB_DEBUG_COUNTER(ivar_get_ic_miss_unset) // Misses on IV read where the cache wasn't set +RB_DEBUG_COUNTER(ivar_get_cc_miss_unset) // Misses on attr_reader where the cache wasn't set /* local variable counts * @@ -121,11 +184,21 @@ RB_DEBUG_COUNTER(gc_major_shady) RB_DEBUG_COUNTER(gc_major_force) RB_DEBUG_COUNTER(gc_major_oldmalloc) +RB_DEBUG_COUNTER(gc_enter_start) +RB_DEBUG_COUNTER(gc_enter_continue) +RB_DEBUG_COUNTER(gc_enter_rest) +RB_DEBUG_COUNTER(gc_enter_finalizer) + +RB_DEBUG_COUNTER(gc_isptr_trial) +RB_DEBUG_COUNTER(gc_isptr_range) +RB_DEBUG_COUNTER(gc_isptr_align) +RB_DEBUG_COUNTER(gc_isptr_maybe) + /* object allocation counts: * * * obj_newobj: newobj counts * * obj_newobj_slowpath: newobj with slowpath counts - * * obj_newobj_wb_unprotected: newobj for wb_unprotecte. + * * obj_newobj_wb_unprotected: newobj for wb_unprotected. * * obj_free: obj_free() counts * * obj_promote: promoted counts (oldgen) * * obj_wb_unprotect: wb unprotect counts @@ -141,15 +214,17 @@ RB_DEBUG_COUNTER(gc_major_oldmalloc) * * [attr] * * _ptr: R?? is not embed. * * _embed: R?? is embed. - * * _transient: R?? uses transient heap. * * type specific attr. * * str_shared: str is shared. * * str_nofree: nofree * * str_fstr: fstr * * hash_empty: hash is empty - * * hash_under4: has under 4 entries - * * hash_ge4: has n entries (4<=n<8) - * * hash_ge8: has n entries (8<=n) + * * hash_1_4: has 1 to 4 entries + * * hash_5_8: has 5 to 8 entries + * * hash_g8: has n entries (n>8) + * * match_under4: has under 4 oniguruma regions allocated + * * match_ge4: has n regions allocated (4<=n<8) + * * match_ge8: has n regions allocated (8<=n) * * data_empty: T_DATA but no memory free. * * data_xfree: free'ed by xfree(). * * data_imm_free: free'ed immediately. @@ -164,8 +239,8 @@ RB_DEBUG_COUNTER(obj_promote) RB_DEBUG_COUNTER(obj_wb_unprotect) RB_DEBUG_COUNTER(obj_obj_embed) -RB_DEBUG_COUNTER(obj_obj_transient) RB_DEBUG_COUNTER(obj_obj_ptr) +RB_DEBUG_COUNTER(obj_obj_complex) RB_DEBUG_COUNTER(obj_str_ptr) RB_DEBUG_COUNTER(obj_str_embed) @@ -174,51 +249,82 @@ RB_DEBUG_COUNTER(obj_str_nofree) RB_DEBUG_COUNTER(obj_str_fstr) RB_DEBUG_COUNTER(obj_ary_embed) -RB_DEBUG_COUNTER(obj_ary_transient) RB_DEBUG_COUNTER(obj_ary_ptr) +RB_DEBUG_COUNTER(obj_ary_extracapa) +/* + ary_shared_create: shared ary by Array#dup and so on. + ary_shared: finished in shard. + ary_shared_root_occupied: shared_root but has only 1 refcnt. + The number (ary_shared - ary_shared_root_occupied) is meaningful. + */ +RB_DEBUG_COUNTER(obj_ary_shared_create) +RB_DEBUG_COUNTER(obj_ary_shared) +RB_DEBUG_COUNTER(obj_ary_shared_root_occupied) RB_DEBUG_COUNTER(obj_hash_empty) -RB_DEBUG_COUNTER(obj_hash_under4) -RB_DEBUG_COUNTER(obj_hash_ge4) -RB_DEBUG_COUNTER(obj_hash_ge8) -RB_DEBUG_COUNTER(obj_hash_array) +RB_DEBUG_COUNTER(obj_hash_1) +RB_DEBUG_COUNTER(obj_hash_2) +RB_DEBUG_COUNTER(obj_hash_3) +RB_DEBUG_COUNTER(obj_hash_4) +RB_DEBUG_COUNTER(obj_hash_5_8) +RB_DEBUG_COUNTER(obj_hash_g8) + +RB_DEBUG_COUNTER(obj_hash_null) +RB_DEBUG_COUNTER(obj_hash_ar) RB_DEBUG_COUNTER(obj_hash_st) -RB_DEBUG_COUNTER(obj_hash_transient) - RB_DEBUG_COUNTER(obj_hash_force_convert) RB_DEBUG_COUNTER(obj_struct_embed) -RB_DEBUG_COUNTER(obj_struct_transient) RB_DEBUG_COUNTER(obj_struct_ptr) -RB_DEBUG_COUNTER(obj_regexp_ptr) - RB_DEBUG_COUNTER(obj_data_empty) RB_DEBUG_COUNTER(obj_data_xfree) RB_DEBUG_COUNTER(obj_data_imm_free) RB_DEBUG_COUNTER(obj_data_zombie) +RB_DEBUG_COUNTER(obj_match_under4) +RB_DEBUG_COUNTER(obj_match_ge4) +RB_DEBUG_COUNTER(obj_match_ge8) RB_DEBUG_COUNTER(obj_match_ptr) -RB_DEBUG_COUNTER(obj_file_ptr) + +RB_DEBUG_COUNTER(obj_iclass_ptr) +RB_DEBUG_COUNTER(obj_class_ptr) +RB_DEBUG_COUNTER(obj_module_ptr) + RB_DEBUG_COUNTER(obj_bignum_ptr) +RB_DEBUG_COUNTER(obj_bignum_embed) +RB_DEBUG_COUNTER(obj_float) +RB_DEBUG_COUNTER(obj_complex) +RB_DEBUG_COUNTER(obj_rational) +RB_DEBUG_COUNTER(obj_regexp_ptr) +RB_DEBUG_COUNTER(obj_file_ptr) RB_DEBUG_COUNTER(obj_symbol) RB_DEBUG_COUNTER(obj_imemo_ment) RB_DEBUG_COUNTER(obj_imemo_iseq) RB_DEBUG_COUNTER(obj_imemo_env) RB_DEBUG_COUNTER(obj_imemo_tmpbuf) -RB_DEBUG_COUNTER(obj_imemo_ast) +RB_DEBUG_COUNTER(obj_imemo_cvar_entry) RB_DEBUG_COUNTER(obj_imemo_cref) RB_DEBUG_COUNTER(obj_imemo_svar) RB_DEBUG_COUNTER(obj_imemo_throw_data) RB_DEBUG_COUNTER(obj_imemo_ifunc) RB_DEBUG_COUNTER(obj_imemo_memo) -RB_DEBUG_COUNTER(obj_imemo_parser_strterm) +RB_DEBUG_COUNTER(obj_imemo_callinfo) +RB_DEBUG_COUNTER(obj_imemo_callcache) +RB_DEBUG_COUNTER(obj_imemo_constcache) +RB_DEBUG_COUNTER(obj_imemo_fields) +RB_DEBUG_COUNTER(obj_imemo_subclasses) +RB_DEBUG_COUNTER(obj_imemo_cdhash) -RB_DEBUG_COUNTER(obj_iclass_ptr) -RB_DEBUG_COUNTER(obj_class_ptr) -RB_DEBUG_COUNTER(obj_module_ptr) +RB_DEBUG_COUNTER(opt_new_hit) +RB_DEBUG_COUNTER(opt_new_miss) + +/* ar_table */ +RB_DEBUG_COUNTER(artable_hint_hit) +RB_DEBUG_COUNTER(artable_hint_miss) +RB_DEBUG_COUNTER(artable_hint_notfound) /* heap function counts * @@ -228,10 +334,12 @@ RB_DEBUG_COUNTER(heap_xmalloc) RB_DEBUG_COUNTER(heap_xrealloc) RB_DEBUG_COUNTER(heap_xfree) -/* transient_heap */ -RB_DEBUG_COUNTER(theap_alloc) -RB_DEBUG_COUNTER(theap_alloc_fail) -RB_DEBUG_COUNTER(theap_evacuate) +// VM sync +RB_DEBUG_COUNTER(vm_sync_lock) +RB_DEBUG_COUNTER(vm_sync_lock_enter) +RB_DEBUG_COUNTER(vm_sync_lock_enter_nb) +RB_DEBUG_COUNTER(vm_sync_lock_enter_cr) +RB_DEBUG_COUNTER(vm_sync_barrier) /* load (not implemented yet) */ /* @@ -243,41 +351,78 @@ RB_DEBUG_COUNTER(load_path_is_not_realpath) #ifndef RUBY_DEBUG_COUNTER_H #define RUBY_DEBUG_COUNTER_H 1 +#include "ruby/internal/config.h" +#include <stddef.h> /* for size_t */ +#include "ruby/ruby.h" /* for VALUE */ + #if !defined(__GNUC__) && USE_DEBUG_COUNTER #error "USE_DEBUG_COUNTER is not supported by other than __GNUC__" #endif enum rb_debug_counter_type { #define RB_DEBUG_COUNTER(name) RB_DEBUG_COUNTER_##name, -#include __FILE__ +#include "debug_counter.h" RB_DEBUG_COUNTER_MAX #undef RB_DEBUG_COUNTER }; #if USE_DEBUG_COUNTER -#include "ruby/ruby.h" - extern size_t rb_debug_counter[]; +RUBY_EXTERN struct rb_ractor_struct *ruby_single_main_ractor; +RUBY_EXTERN void rb_debug_counter_add_atomic(enum rb_debug_counter_type type, int add); inline static int rb_debug_counter_add(enum rb_debug_counter_type type, int add, int cond) { if (cond) { - rb_debug_counter[(int)type] += add; + if (ruby_single_main_ractor != NULL) { + rb_debug_counter[(int)type] += add; + } + else { + rb_debug_counter_add_atomic(type, add); + } } return cond; } +inline static int +rb_debug_counter_max(enum rb_debug_counter_type type, unsigned int num) +{ + // TODO: sync + if (rb_debug_counter[(int)type] < num) { + rb_debug_counter[(int)type] = num; + return 1; + } + else { + return 0; + } +} + +VALUE rb_debug_counter_reset(VALUE klass); +VALUE rb_debug_counter_show(VALUE klass); + #define RB_DEBUG_COUNTER_INC(type) rb_debug_counter_add(RB_DEBUG_COUNTER_##type, 1, 1) #define RB_DEBUG_COUNTER_INC_UNLESS(type, cond) (!rb_debug_counter_add(RB_DEBUG_COUNTER_##type, 1, !(cond))) -#define RB_DEBUG_COUNTER_INC_IF(type, cond) rb_debug_counter_add(RB_DEBUG_COUNTER_##type, 1, (cond)) +#define RB_DEBUG_COUNTER_INC_IF(type, cond) rb_debug_counter_add(RB_DEBUG_COUNTER_##type, 1, !!(cond)) +#define RB_DEBUG_COUNTER_ADD(type, num) rb_debug_counter_add(RB_DEBUG_COUNTER_##type, (num), 1) +#define RB_DEBUG_COUNTER_SETMAX(type, num) rb_debug_counter_max(RB_DEBUG_COUNTER_##type, (unsigned int)(num)) #else #define RB_DEBUG_COUNTER_INC(type) ((void)0) -#define RB_DEBUG_COUNTER_INC_UNLESS(type, cond) (cond) -#define RB_DEBUG_COUNTER_INC_IF(type, cond) (cond) +#define RB_DEBUG_COUNTER_INC_UNLESS(type, cond) (!!(cond)) +#define RB_DEBUG_COUNTER_INC_IF(type, cond) (!!(cond)) +#define RB_DEBUG_COUNTER_ADD(type, num) ((void)0) +#define RB_DEBUG_COUNTER_SETMAX(type, num) 0 #endif void rb_debug_counter_show_results(const char *msg); +RUBY_SYMBOL_EXPORT_BEGIN + +size_t ruby_debug_counter_get(const char **names_ptr, size_t *counters_ptr); +void ruby_debug_counter_reset(void); +void ruby_debug_counter_show_at_exit(int enable); + +RUBY_SYMBOL_EXPORT_END + #endif /* RUBY_DEBUG_COUNTER_H */ |
