1 /**********************************************************************
5 created at: Tue Feb 21 16:51:18 2017
7 Copyright (C) 2017 Koichi Sasada
9 **********************************************************************/
11 #ifndef USE_DEBUG_COUNTER
12 #define USE_DEBUG_COUNTER 0
15 #ifdef RB_DEBUG_COUNTER
17 // method cache (IMC: inline method cache)
18 RB_DEBUG_COUNTER(mc_inline_hit
) // IMC hit
19 RB_DEBUG_COUNTER(mc_inline_miss_klass
) // IMC miss by different class
20 RB_DEBUG_COUNTER(mc_inline_miss_invalidated
) // IMC miss by invalidated ME
21 RB_DEBUG_COUNTER(mc_inline_miss_empty
) // IMC miss because prev is empty slot
22 RB_DEBUG_COUNTER(mc_inline_miss_same_cc
) // IMC miss, but same CC
23 RB_DEBUG_COUNTER(mc_inline_miss_same_cme
) // IMC miss, but same CME
24 RB_DEBUG_COUNTER(mc_inline_miss_same_def
) // IMC miss, but same definition
25 RB_DEBUG_COUNTER(mc_inline_miss_diff
) // IMC miss, different methods
27 RB_DEBUG_COUNTER(cvar_write_inline_hit
) // cvar cache hit on write
28 RB_DEBUG_COUNTER(cvar_read_inline_hit
) // cvar cache hit on read
29 RB_DEBUG_COUNTER(cvar_inline_miss
) // miss inline cache
30 RB_DEBUG_COUNTER(cvar_class_invalidate
) // invalidate cvar cache when define a cvar that's defined on a subclass
31 RB_DEBUG_COUNTER(cvar_include_invalidate
) // invalidate cvar cache on module include or prepend
33 RB_DEBUG_COUNTER(mc_cme_complement
) // number of acquiring complement CME
34 RB_DEBUG_COUNTER(mc_cme_complement_hit
) // number of cache hit for complemented CME
36 RB_DEBUG_COUNTER(mc_search
) // count for method lookup in class tree
37 RB_DEBUG_COUNTER(mc_search_notfound
) // method lookup, but not found
38 RB_DEBUG_COUNTER(mc_search_super
) // total traversed classes
41 RB_DEBUG_COUNTER(ci_packed
) // number of packed CI
42 RB_DEBUG_COUNTER(ci_kw
) // non-packed CI w/ keywords
43 RB_DEBUG_COUNTER(ci_nokw
) // non-packed CI w/o keywords
44 RB_DEBUG_COUNTER(ci_runtime
) // creating temporary CI
47 RB_DEBUG_COUNTER(cc_new
) // number of CC
48 RB_DEBUG_COUNTER(cc_temp
) // dummy CC (stack-allocated)
49 RB_DEBUG_COUNTER(cc_found_in_ccs
) // count for CC lookup success in CCS
50 RB_DEBUG_COUNTER(cc_not_found_in_ccs
) // count for CC lookup success in CCS
52 RB_DEBUG_COUNTER(cc_ent_invalidate
) // count for invalidating cc (cc->klass = 0)
53 RB_DEBUG_COUNTER(cc_cme_invalidate
) // count for invalidating CME
55 RB_DEBUG_COUNTER(cc_invalidate_leaf
) // count for invalidating klass if klass has no-subclasses
56 RB_DEBUG_COUNTER(cc_invalidate_leaf_ccs
) // corresponding CCS
57 RB_DEBUG_COUNTER(cc_invalidate_leaf_callable
) // complimented cache (no-subclasses)
58 RB_DEBUG_COUNTER(cc_invalidate_tree
) // count for invalidating klass if klass has subclasses
59 RB_DEBUG_COUNTER(cc_invalidate_tree_cme
) // cme if cme is found in this class or superclasses
60 RB_DEBUG_COUNTER(cc_invalidate_tree_callable
) // complimented cache (subclasses)
61 RB_DEBUG_COUNTER(cc_invalidate_negative
) // count for invalidating negative cache
63 RB_DEBUG_COUNTER(ccs_free
) // count for free'ing ccs
64 RB_DEBUG_COUNTER(ccs_maxlen
) // maximum length of ccs
65 RB_DEBUG_COUNTER(ccs_found
) // count for finding corresponding ccs on method lookup
66 RB_DEBUG_COUNTER(ccs_not_found
) // count for not found corresponding ccs on method lookup
69 RB_DEBUG_COUNTER(call0_public
)
70 RB_DEBUG_COUNTER(call0_other
)
71 RB_DEBUG_COUNTER(gccct_hit
)
72 RB_DEBUG_COUNTER(gccct_miss
)
73 RB_DEBUG_COUNTER(gccct_null
)
76 RB_DEBUG_COUNTER(iseq_num
) // number of total created iseq
77 RB_DEBUG_COUNTER(iseq_cd_num
) // number of total created cd (call_data)
80 * call cache fastpath usage
82 RB_DEBUG_COUNTER(ccf_general
)
83 RB_DEBUG_COUNTER(ccf_iseq_setup
)
84 RB_DEBUG_COUNTER(ccf_iseq_setup_0start
)
85 RB_DEBUG_COUNTER(ccf_iseq_setup_tailcall_0start
)
86 RB_DEBUG_COUNTER(ccf_iseq_fix
) /* several functions created with tool/mk_call_iseq_optimized.rb */
87 RB_DEBUG_COUNTER(ccf_iseq_opt
) /* has_opt == TRUE (has optional parameters), but other flags are FALSE */
88 RB_DEBUG_COUNTER(ccf_iseq_kw1
) /* vm_call_iseq_setup_kwparm_kwarg() */
89 RB_DEBUG_COUNTER(ccf_iseq_kw2
) /* vm_call_iseq_setup_kwparm_nokwarg() */
90 RB_DEBUG_COUNTER(ccf_cfunc
)
91 RB_DEBUG_COUNTER(ccf_cfunc_with_frame
)
92 RB_DEBUG_COUNTER(ccf_ivar
) /* attr_reader */
93 RB_DEBUG_COUNTER(ccf_attrset
) /* attr_writer */
94 RB_DEBUG_COUNTER(ccf_method_missing
)
95 RB_DEBUG_COUNTER(ccf_zsuper
)
96 RB_DEBUG_COUNTER(ccf_bmethod
)
97 RB_DEBUG_COUNTER(ccf_opt_send
)
98 RB_DEBUG_COUNTER(ccf_opt_call
)
99 RB_DEBUG_COUNTER(ccf_opt_block_call
)
100 RB_DEBUG_COUNTER(ccf_opt_struct_aref
)
101 RB_DEBUG_COUNTER(ccf_opt_struct_aset
)
102 RB_DEBUG_COUNTER(ccf_super_method
)
103 RB_DEBUG_COUNTER(ccf_cfunc_other
)
104 RB_DEBUG_COUNTER(ccf_cfunc_only_splat
)
105 RB_DEBUG_COUNTER(ccf_cfunc_only_splat_kw
)
106 RB_DEBUG_COUNTER(ccf_iseq_bmethod
)
107 RB_DEBUG_COUNTER(ccf_noniseq_bmethod
)
108 RB_DEBUG_COUNTER(ccf_opt_send_complex
)
109 RB_DEBUG_COUNTER(ccf_opt_send_simple
)
112 * control frame push counts.
114 * * frame_push: frame push counts.
115 * * frame_push_*: frame push counts per each type.
116 * * frame_R2R: Ruby frame to Ruby frame
117 * * frame_R2C: Ruby frame to C frame
118 * * frame_C2C: C frame to C frame
119 * * frame_C2R: C frame to Ruby frame
121 RB_DEBUG_COUNTER(frame_push
)
122 RB_DEBUG_COUNTER(frame_push_method
)
123 RB_DEBUG_COUNTER(frame_push_block
)
124 RB_DEBUG_COUNTER(frame_push_class
)
125 RB_DEBUG_COUNTER(frame_push_top
)
126 RB_DEBUG_COUNTER(frame_push_cfunc
)
127 RB_DEBUG_COUNTER(frame_push_ifunc
)
128 RB_DEBUG_COUNTER(frame_push_eval
)
129 RB_DEBUG_COUNTER(frame_push_rescue
)
130 RB_DEBUG_COUNTER(frame_push_dummy
)
132 RB_DEBUG_COUNTER(frame_R2R
)
133 RB_DEBUG_COUNTER(frame_R2C
)
134 RB_DEBUG_COUNTER(frame_C2C
)
135 RB_DEBUG_COUNTER(frame_C2R
)
137 /* instance variable counts */
138 RB_DEBUG_COUNTER(ivar_get_obj_hit
) // Only T_OBJECT hits
139 RB_DEBUG_COUNTER(ivar_get_obj_miss
) // Only T_OBJECT misses
140 RB_DEBUG_COUNTER(ivar_get_ic_hit
) // All hits
141 RB_DEBUG_COUNTER(ivar_get_ic_miss
) // All misses
142 RB_DEBUG_COUNTER(ivar_set_ic_hit
) // All hits
143 RB_DEBUG_COUNTER(ivar_set_obj_hit
) // Only T_OBJECT hits
144 RB_DEBUG_COUNTER(ivar_set_obj_miss
) // Only T_OBJECT misses
145 RB_DEBUG_COUNTER(ivar_set_ic_miss
) // All misses
146 RB_DEBUG_COUNTER(ivar_set_ic_miss_noobject
) // Miss because non T_OBJECT
147 RB_DEBUG_COUNTER(ivar_get_base
) // Calls to `rb_ivar_get` (very slow path)
148 RB_DEBUG_COUNTER(ivar_set_base
) // Calls to `ivar_set` (very slow path)
149 RB_DEBUG_COUNTER(ivar_get_ic_miss_set
) // Misses on IV reads where the cache was wrong
150 RB_DEBUG_COUNTER(ivar_get_cc_miss_set
) // Misses on attr_reader where the cache was wrong
151 RB_DEBUG_COUNTER(ivar_get_ic_miss_unset
) // Misses on IV read where the cache wasn't set
152 RB_DEBUG_COUNTER(ivar_get_cc_miss_unset
) // Misses on attr_reader where the cache wasn't set
154 /* local variable counts
156 * * lvar_get: total lvar get counts (VM insn)
157 * * lvar_get_dynamic: lvar get counts if accessing upper env (VM insn)
158 * * lvar_set*: same as "get"
159 * * lvar_set_slowpath: counts using vm_env_write_slowpath()
161 RB_DEBUG_COUNTER(lvar_get
)
162 RB_DEBUG_COUNTER(lvar_get_dynamic
)
163 RB_DEBUG_COUNTER(lvar_set
)
164 RB_DEBUG_COUNTER(lvar_set_dynamic
)
165 RB_DEBUG_COUNTER(lvar_set_slowpath
)
169 * * count: simple count
172 * * other suffix is corresponding to last_gc_info or
173 * gc_profile_record_flag in gc.c.
175 RB_DEBUG_COUNTER(gc_count
)
176 RB_DEBUG_COUNTER(gc_minor_newobj
)
177 RB_DEBUG_COUNTER(gc_minor_malloc
)
178 RB_DEBUG_COUNTER(gc_minor_method
)
179 RB_DEBUG_COUNTER(gc_minor_capi
)
180 RB_DEBUG_COUNTER(gc_minor_stress
)
181 RB_DEBUG_COUNTER(gc_major_nofree
)
182 RB_DEBUG_COUNTER(gc_major_oldgen
)
183 RB_DEBUG_COUNTER(gc_major_shady
)
184 RB_DEBUG_COUNTER(gc_major_force
)
185 RB_DEBUG_COUNTER(gc_major_oldmalloc
)
187 RB_DEBUG_COUNTER(gc_enter_start
)
188 RB_DEBUG_COUNTER(gc_enter_continue
)
189 RB_DEBUG_COUNTER(gc_enter_rest
)
190 RB_DEBUG_COUNTER(gc_enter_finalizer
)
192 RB_DEBUG_COUNTER(gc_isptr_trial
)
193 RB_DEBUG_COUNTER(gc_isptr_range
)
194 RB_DEBUG_COUNTER(gc_isptr_align
)
195 RB_DEBUG_COUNTER(gc_isptr_maybe
)
197 /* object allocation counts:
199 * * obj_newobj: newobj counts
200 * * obj_newobj_slowpath: newobj with slowpath counts
201 * * obj_newobj_wb_unprotected: newobj for wb_unprotected.
202 * * obj_free: obj_free() counts
203 * * obj_promote: promoted counts (oldgen)
204 * * obj_wb_unprotect: wb unprotect counts
206 * * obj_[type]_[attr]: *free'ed counts* for each type.
207 * Note that it is not a allocated counts.
212 * * _xxx: T_XXX (hash, struct, ...)
215 * * _ptr: R?? is not embed.
216 * * _embed: R?? is embed.
217 * * type specific attr.
218 * * str_shared: str is shared.
219 * * str_nofree: nofree
221 * * hash_empty: hash is empty
222 * * hash_1_4: has 1 to 4 entries
223 * * hash_5_8: has 5 to 8 entries
224 * * hash_g8: has n entries (n>8)
225 * * match_under4: has under 4 oniguruma regions allocated
226 * * match_ge4: has n regions allocated (4<=n<8)
227 * * match_ge8: has n regions allocated (8<=n)
228 * * data_empty: T_DATA but no memory free.
229 * * data_xfree: free'ed by xfree().
230 * * data_imm_free: free'ed immediately.
231 * * data_zombie: free'ed with zombie.
232 * * imemo_*: T_IMEMO with each type.
234 RB_DEBUG_COUNTER(obj_newobj
)
235 RB_DEBUG_COUNTER(obj_newobj_slowpath
)
236 RB_DEBUG_COUNTER(obj_newobj_wb_unprotected
)
237 RB_DEBUG_COUNTER(obj_free
)
238 RB_DEBUG_COUNTER(obj_promote
)
239 RB_DEBUG_COUNTER(obj_wb_unprotect
)
241 RB_DEBUG_COUNTER(obj_obj_embed
)
242 RB_DEBUG_COUNTER(obj_obj_ptr
)
243 RB_DEBUG_COUNTER(obj_obj_too_complex
)
245 RB_DEBUG_COUNTER(obj_str_ptr
)
246 RB_DEBUG_COUNTER(obj_str_embed
)
247 RB_DEBUG_COUNTER(obj_str_shared
)
248 RB_DEBUG_COUNTER(obj_str_nofree
)
249 RB_DEBUG_COUNTER(obj_str_fstr
)
251 RB_DEBUG_COUNTER(obj_ary_embed
)
252 RB_DEBUG_COUNTER(obj_ary_ptr
)
253 RB_DEBUG_COUNTER(obj_ary_extracapa
)
255 ary_shared_create: shared ary by Array#dup and so on.
256 ary_shared: finished in shard.
257 ary_shared_root_occupied: shared_root but has only 1 refcnt.
258 The number (ary_shared - ary_shared_root_occupied) is meaningful.
260 RB_DEBUG_COUNTER(obj_ary_shared_create
)
261 RB_DEBUG_COUNTER(obj_ary_shared
)
262 RB_DEBUG_COUNTER(obj_ary_shared_root_occupied
)
264 RB_DEBUG_COUNTER(obj_hash_empty
)
265 RB_DEBUG_COUNTER(obj_hash_1
)
266 RB_DEBUG_COUNTER(obj_hash_2
)
267 RB_DEBUG_COUNTER(obj_hash_3
)
268 RB_DEBUG_COUNTER(obj_hash_4
)
269 RB_DEBUG_COUNTER(obj_hash_5_8
)
270 RB_DEBUG_COUNTER(obj_hash_g8
)
272 RB_DEBUG_COUNTER(obj_hash_null
)
273 RB_DEBUG_COUNTER(obj_hash_ar
)
274 RB_DEBUG_COUNTER(obj_hash_st
)
275 RB_DEBUG_COUNTER(obj_hash_force_convert
)
277 RB_DEBUG_COUNTER(obj_struct_embed
)
278 RB_DEBUG_COUNTER(obj_struct_ptr
)
280 RB_DEBUG_COUNTER(obj_data_empty
)
281 RB_DEBUG_COUNTER(obj_data_xfree
)
282 RB_DEBUG_COUNTER(obj_data_imm_free
)
283 RB_DEBUG_COUNTER(obj_data_zombie
)
285 RB_DEBUG_COUNTER(obj_match_under4
)
286 RB_DEBUG_COUNTER(obj_match_ge4
)
287 RB_DEBUG_COUNTER(obj_match_ge8
)
288 RB_DEBUG_COUNTER(obj_match_ptr
)
290 RB_DEBUG_COUNTER(obj_iclass_ptr
)
291 RB_DEBUG_COUNTER(obj_class_ptr
)
292 RB_DEBUG_COUNTER(obj_module_ptr
)
294 RB_DEBUG_COUNTER(obj_bignum_ptr
)
295 RB_DEBUG_COUNTER(obj_bignum_embed
)
296 RB_DEBUG_COUNTER(obj_float
)
297 RB_DEBUG_COUNTER(obj_complex
)
298 RB_DEBUG_COUNTER(obj_rational
)
300 RB_DEBUG_COUNTER(obj_regexp_ptr
)
301 RB_DEBUG_COUNTER(obj_file_ptr
)
302 RB_DEBUG_COUNTER(obj_symbol
)
304 RB_DEBUG_COUNTER(obj_imemo_ment
)
305 RB_DEBUG_COUNTER(obj_imemo_iseq
)
306 RB_DEBUG_COUNTER(obj_imemo_env
)
307 RB_DEBUG_COUNTER(obj_imemo_tmpbuf
)
308 RB_DEBUG_COUNTER(obj_imemo_ast
)
309 RB_DEBUG_COUNTER(obj_imemo_cref
)
310 RB_DEBUG_COUNTER(obj_imemo_svar
)
311 RB_DEBUG_COUNTER(obj_imemo_throw_data
)
312 RB_DEBUG_COUNTER(obj_imemo_ifunc
)
313 RB_DEBUG_COUNTER(obj_imemo_memo
)
314 RB_DEBUG_COUNTER(obj_imemo_parser_strterm
)
315 RB_DEBUG_COUNTER(obj_imemo_callinfo
)
316 RB_DEBUG_COUNTER(obj_imemo_callcache
)
317 RB_DEBUG_COUNTER(obj_imemo_constcache
)
320 RB_DEBUG_COUNTER(artable_hint_hit
)
321 RB_DEBUG_COUNTER(artable_hint_miss
)
322 RB_DEBUG_COUNTER(artable_hint_notfound
)
324 /* heap function counts
326 * * heap_xmalloc/realloc/xfree: call counts
328 RB_DEBUG_COUNTER(heap_xmalloc
)
329 RB_DEBUG_COUNTER(heap_xrealloc
)
330 RB_DEBUG_COUNTER(heap_xfree
)
333 RB_DEBUG_COUNTER(vm_sync_lock
)
334 RB_DEBUG_COUNTER(vm_sync_lock_enter
)
335 RB_DEBUG_COUNTER(vm_sync_lock_enter_nb
)
336 RB_DEBUG_COUNTER(vm_sync_lock_enter_cr
)
337 RB_DEBUG_COUNTER(vm_sync_barrier
)
339 /* load (not implemented yet) */
341 RB_DEBUG_COUNTER(load_files)
342 RB_DEBUG_COUNTER(load_path_is_not_realpath)
346 #ifndef RUBY_DEBUG_COUNTER_H
347 #define RUBY_DEBUG_COUNTER_H 1
349 #include "ruby/internal/config.h"
350 #include <stddef.h> /* for size_t */
351 #include "ruby/ruby.h" /* for VALUE */
353 #if !defined(__GNUC__) && USE_DEBUG_COUNTER
354 #error "USE_DEBUG_COUNTER is not supported by other than __GNUC__"
357 enum rb_debug_counter_type
{
358 #define RB_DEBUG_COUNTER(name) RB_DEBUG_COUNTER_##name,
361 #undef RB_DEBUG_COUNTER
364 #if USE_DEBUG_COUNTER
365 extern size_t rb_debug_counter
[];
366 RUBY_EXTERN
struct rb_ractor_struct
*ruby_single_main_ractor
;
367 RUBY_EXTERN
void rb_debug_counter_add_atomic(enum rb_debug_counter_type type
, int add
);
370 rb_debug_counter_add(enum rb_debug_counter_type type
, int add
, int cond
)
373 if (ruby_single_main_ractor
!= NULL
) {
374 rb_debug_counter
[(int)type
] += add
;
377 rb_debug_counter_add_atomic(type
, add
);
384 rb_debug_counter_max(enum rb_debug_counter_type type
, unsigned int num
)
387 if (rb_debug_counter
[(int)type
] < num
) {
388 rb_debug_counter
[(int)type
] = num
;
396 VALUE
rb_debug_counter_reset(VALUE klass
);
397 VALUE
rb_debug_counter_show(VALUE klass
);
399 #define RB_DEBUG_COUNTER_INC(type) rb_debug_counter_add(RB_DEBUG_COUNTER_##type, 1, 1)
400 #define RB_DEBUG_COUNTER_INC_UNLESS(type, cond) (!rb_debug_counter_add(RB_DEBUG_COUNTER_##type, 1, !(cond)))
401 #define RB_DEBUG_COUNTER_INC_IF(type, cond) rb_debug_counter_add(RB_DEBUG_COUNTER_##type, 1, !!(cond))
402 #define RB_DEBUG_COUNTER_ADD(type, num) rb_debug_counter_add(RB_DEBUG_COUNTER_##type, (num), 1)
403 #define RB_DEBUG_COUNTER_SETMAX(type, num) rb_debug_counter_max(RB_DEBUG_COUNTER_##type, (unsigned int)(num))
406 #define RB_DEBUG_COUNTER_INC(type) ((void)0)
407 #define RB_DEBUG_COUNTER_INC_UNLESS(type, cond) (!!(cond))
408 #define RB_DEBUG_COUNTER_INC_IF(type, cond) (!!(cond))
409 #define RB_DEBUG_COUNTER_ADD(type, num) ((void)0)
410 #define RB_DEBUG_COUNTER_SETMAX(type, num) 0
413 void rb_debug_counter_show_results(const char *msg
);
415 RUBY_SYMBOL_EXPORT_BEGIN
417 size_t ruby_debug_counter_get(const char **names_ptr
, size_t *counters_ptr
);
418 void ruby_debug_counter_reset(void);
419 void ruby_debug_counter_show_at_exit(int enable
);
421 RUBY_SYMBOL_EXPORT_END
423 #endif /* RUBY_DEBUG_COUNTER_H */