ruby-changes:52629
From: ko1 <ko1@a...>
Date: Wed, 26 Sep 2018 03:13:35 +0900 (JST)
Subject: [ruby-changes:52629] ko1:r64841 (trunk): refactoring debug_counter.
ko1 2018-09-26 03:13:29 +0900 (Wed, 26 Sep 2018) New Revision: 64841 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=64841 Log: refactoring debug_counter. * debug_counter.h: add comments for each counters. * debug_counter.h: add some counters (see added comments for details). * obj_newobj * obj_newobj_slowpath * obj_newobj_wb_unprotected * obj_hash_empty * obj_hash_under4 * obj_hash_ge4 * obj_hash_ge8 * heap_xmalloc * heap_xrealloc * heap_xfree * gc.c: add some debug counters (see the above list). * debug_counter.c (rb_debug_counter_show_results): accept a header message. * signal.c (ruby_default_signal): show debug counter results and malloc info (rb_malloc_info_show_results()) before SIGNAL exit. Modified files: trunk/debug_counter.c trunk/debug_counter.h trunk/gc.c trunk/signal.c Index: signal.c =================================================================== --- signal.c (revision 64840) +++ signal.c (revision 64841) @@ -395,9 +395,17 @@ interrupt_init(int argc, VALUE *argv, VA https://github.com/ruby/ruby/blob/trunk/signal.c#L395 return rb_call_super(2, args); } +#include "debug_counter.h" +void rb_malloc_info_show_results(void); /* gc.c */ + void ruby_default_signal(int sig) { +#if USE_DEBUG_COUNTER + rb_debug_counter_show_results("killed by signal."); +#endif + rb_malloc_info_show_results(); + signal(sig, SIG_DFL); raise(sig); } Index: gc.c =================================================================== --- gc.c (revision 64840) +++ gc.c (revision 64841) @@ -1948,6 +1948,9 @@ newobj_of(VALUE klass, VALUE flags, VALU https://github.com/ruby/ruby/blob/trunk/gc.c#L1948 rb_objspace_t *objspace = &rb_objspace; VALUE obj; + RB_DEBUG_COUNTER_INC(obj_newobj); + (void)RB_DEBUG_COUNTER_INC_IF(obj_newobj_wb_unprotected, !wb_protected); + #if GC_DEBUG_STRESS_TO_CLASS if (UNLIKELY(stress_to_class)) { long i, cnt = RARRAY_LEN(stress_to_class); @@ -1964,6 +1967,8 @@ newobj_of(VALUE klass, VALUE flags, VALU https://github.com/ruby/ruby/blob/trunk/gc.c#L1967 return newobj_init(klass, flags, v1, v2, v3, wb_protected, objspace, obj); } else { + RB_DEBUG_COUNTER_INC(obj_newobj_slowpath); + return wb_protected ? newobj_slowpath_wb_protected(klass, flags, v1, v2, v3, objspace) : newobj_slowpath_wb_unprotected(klass, flags, v1, v2, v3, objspace); @@ -2256,7 +2261,20 @@ obj_free(rb_objspace_t *objspace, VALUE https://github.com/ruby/ruby/blob/trunk/gc.c#L2261 case T_HASH: if (RANY(obj)->as.hash.ntbl) { st_free_table(RANY(obj)->as.hash.ntbl); + + if (RHASH_SIZE(obj) >= 8) { + RB_DEBUG_COUNTER_INC(obj_hash_ge8); + } + if (RHASH_SIZE(obj) >= 4) { + RB_DEBUG_COUNTER_INC(obj_hash_ge4); + } + else { + RB_DEBUG_COUNTER_INC(obj_hash_under4); + } } + else { + RB_DEBUG_COUNTER_INC(obj_hash_empty); + } break; case T_REGEXP: if (RANY(obj)->as.regexp.ptr) { @@ -7959,6 +7977,7 @@ objspace_xmalloc0(rb_objspace_t *objspac https://github.com/ruby/ruby/blob/trunk/gc.c#L7977 size = objspace_malloc_prepare(objspace, size); TRY_WITH_GC(mem = malloc(size)); + RB_DEBUG_COUNTER_INC(heap_xmalloc); return objspace_malloc_fixup(objspace, mem, size); } @@ -8012,11 +8031,11 @@ objspace_xrealloc(rb_objspace_t *objspac https://github.com/ruby/ruby/blob/trunk/gc.c#L8031 objspace_malloc_increase(objspace, mem, new_size, old_size, MEMOP_TYPE_REALLOC); + RB_DEBUG_COUNTER_INC(heap_xrealloc); return mem; } -#if CALC_EXACT_MALLOC_SIZE -#if USE_GC_MALLOC_OBJ_INFO_DETAILS +#if CALC_EXACT_MALLOC_SIZE && USE_GC_MALLOC_OBJ_INFO_DETAILS #define MALLOC_INFO_GEN_SIZE 100 #define MALLOC_INFO_SIZE_SIZE 10 @@ -8037,8 +8056,8 @@ mmalloc_info_file_i(st_data_t key, st_da https://github.com/ruby/ruby/blob/trunk/gc.c#L8056 } __attribute__((destructor)) -static void -malloc_info_show_results(void) +void +rb_malloc_info_show_results(void) { int i; @@ -8064,7 +8083,11 @@ malloc_info_show_results(void) https://github.com/ruby/ruby/blob/trunk/gc.c#L8083 st_foreach(malloc_info_file_table, mmalloc_info_file_i, 0); } } -#endif +#else +void +rb_malloc_info_show_results(void) +{ +} #endif static void @@ -8129,6 +8152,7 @@ objspace_xfree(rb_objspace_t *objspace, https://github.com/ruby/ruby/blob/trunk/gc.c#L8152 old_size = objspace_malloc_size(objspace, ptr, old_size); free(ptr); + RB_DEBUG_COUNTER_INC(heap_xfree); objspace_malloc_increase(objspace, ptr, 0, old_size, MEMOP_TYPE_FREE); } Index: debug_counter.c =================================================================== --- debug_counter.c (revision 64840) +++ debug_counter.c (revision 64841) @@ -9,9 +9,9 @@ https://github.com/ruby/ruby/blob/trunk/debug_counter.c#L9 **********************************************************************/ #include "debug_counter.h" -#include <stdio.h> - #if USE_DEBUG_COUNTER +#include <stdio.h> +#include <locale.h> #include "internal.h" static const char *const debug_counter_names[] = { @@ -23,19 +23,33 @@ static const char *const debug_counter_n https://github.com/ruby/ruby/blob/trunk/debug_counter.c#L23 size_t rb_debug_counter[numberof(debug_counter_names)]; -__attribute__((destructor)) -static void -rb_debug_counter_show_results(void) +void +rb_debug_counter_show_results(const char *msg) { const char *env = getenv("RUBY_DEBUG_COUNTER_DISABLE"); + + setlocale(LC_NUMERIC, ""); + if (env == NULL || strcmp("1", env) != 0) { int i; + fprintf(stderr, "[RUBY_DEBUG_COUNTER]\t%d %s\n", getpid(), msg); for (i=0; i<RB_DEBUG_COUNTER_MAX; i++) { - fprintf(stderr, "[RUBY_DEBUG_COUNTER]\t%s\t%"PRIuSIZE"\n", + fprintf(stderr, "[RUBY_DEBUG_COUNTER]\t%-30s\t%'12"PRIuSIZE"\n", debug_counter_names[i], rb_debug_counter[i]); } } } +__attribute__((destructor)) +static void +debug_counter_show_results_at_exit(void) +{ + rb_debug_counter_show_results("normal exit."); +} +#else +void +rb_debug_counter_show_results(const char *msg) +{ +} #endif /* USE_DEBUG_COUNTER */ Index: debug_counter.h =================================================================== --- debug_counter.h (revision 64840) +++ debug_counter.h (revision 64841) @@ -14,7 +14,19 @@ https://github.com/ruby/ruby/blob/trunk/debug_counter.h#L14 #ifdef RB_DEBUG_COUNTER -/* method search */ +/* + * 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. + */ RB_DEBUG_COUNTER(mc_inline_hit) RB_DEBUG_COUNTER(mc_inline_miss) RB_DEBUG_COUNTER(mc_global_hit) @@ -25,7 +37,17 @@ RB_DEBUG_COUNTER(mc_cme_complement) https://github.com/ruby/ruby/blob/trunk/debug_counter.h#L37 RB_DEBUG_COUNTER(mc_cme_complement_hit) RB_DEBUG_COUNTER(mc_search_super) -/* ivar access */ +/* 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) @@ -40,16 +62,53 @@ RB_DEBUG_COUNTER(ivar_set_ic_miss_noobje https://github.com/ruby/ruby/blob/trunk/debug_counter.h#L62 RB_DEBUG_COUNTER(ivar_get_base) RB_DEBUG_COUNTER(ivar_set_base) -/* lvar access */ +/* local variable counts + * + * * lvar_get: total lvar get counts (VM insn) + * * lvar_get_dynamic: lvar get counts if accessing upper env (VM insn) + * * lvar_set*: same as "get" + * * lvar_set_slowpath: counts using vm_env_write_slowpath() + */ RB_DEBUG_COUNTER(lvar_get) RB_DEBUG_COUNTER(lvar_get_dynamic) RB_DEBUG_COUNTER(lvar_set) RB_DEBUG_COUNTER(lvar_set_dynamic) RB_DEBUG_COUNTER(lvar_set_slowpath) -/* object counts */ +/* object allocation counts: + * + * * obj_newobj: newobj counts + * * obj_newobj_slowpath: newobj with slowpath counts + * * obj_newobj_wb_unprotected: newobj for wb_unprotecte. + * * obj_free: obj_free() counts + * + * * obj_[type]_[attr]: free'ed counts for each type. + * * [type] + * * _obj: T_OBJECT + * * _str: T_STRING + * * _ary: T_ARRAY + * * _hash: T_HASH + * + * * [attr] + * * _ptr: R?? is not embed. + * * _embed: R?? is embed. + * * 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) + */ +RB_DEBUG_COUNTER(obj_newobj) +RB_DEBUG_COUNTER(obj_newobj_slowpath) +RB_DEBUG_COUNTER(obj_newobj_wb_unprotected) RB_DEBUG_COUNTER(obj_free) +RB_DEBUG_COUNTER(obj_obj_ptr) +RB_DEBUG_COUNTER(obj_obj_embed) + RB_DEBUG_COUNTER(obj_str_ptr) RB_DEBUG_COUNTER(obj_str_embed) RB_DEBUG_COUNTER(obj_str_shared) @@ -59,13 +118,24 @@ RB_DEBUG_COUNTER(obj_str_fstr) https://github.com/ruby/ruby/blob/trunk/debug_counter.h#L118 RB_DEBUG_COUNTER(obj_ary_ptr) RB_DEBUG_COUNTER(obj_ary_embed) -RB_DEBUG_COUNTER(obj_obj_ptr) -RB_DEBUG_COUNTER(obj_obj_embed) +RB_DEBUG_COUNTER(obj_hash_empty) +RB_DEBUG_COUNTER(obj_hash_under4) +RB_DEBUG_COUNTER(obj_hash_ge4) +RB_DEBUG_COUNTER(obj_hash_ge8) + +/* heap function counts + * + * * heap_xmalloc/realloc/xfree: call counts + */ +RB_DEBUG_COUNTER(heap_xmalloc) +RB_DEBUG_COUNTER(heap_xrealloc) +RB_DEBUG_COUNTER(heap_xfree) -/* load */ +/* load (not implemented yet) */ +/* RB_DEBUG_COUNTER(load_files) RB_DEBUG_COUNTER(load_path_is_not_realpath) - +*/ #endif #ifndef RUBY_DEBUG_COUNTER_H @@ -106,4 +176,6 @@ rb_debug_counter_add(enum rb_debug_count https://github.com/ruby/ruby/blob/trunk/debug_counter.h#L176 #define RB_DEBUG_COUNTER_INC_IF(type, cond) (cond) #endif +void rb_debug_counter_show_results(const char *msg); + #endif /* RUBY_DEBUG_COUNTER_H */ -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/