diff options
author | Peter Zhu <peter@peterzhu.ca> | 2021-11-25 09:31:58 -0500 |
---|---|---|
committer | Peter Zhu <peter@peterzhu.ca> | 2021-11-25 10:33:17 -0500 |
commit | 6157619bb68e4307cdf065cb73d5bfcec30d042d (patch) | |
tree | d0fff7d4c5bae8809eb6bafebbf567fa30b4dcdc /gc.c | |
parent | 09ef048b34dd4aed65ec2899315a91d25ffa7629 (diff) |
Add GC.stat_size_pool to get stats for a size pool
GC.stat_size_pool will return stats for a particular size pool. This is
used for the Variable Width Allocation feature.
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/5169
Diffstat (limited to 'gc.c')
-rw-r--r-- | gc.c | 95 |
1 files changed, 95 insertions, 0 deletions
@@ -10675,6 +10675,101 @@ rb_gc_stat(VALUE key) } } + +enum gc_stat_size_pool_sym { + gc_stat_size_pool_sym_slot_size, + gc_stat_size_pool_sym_heap_allocatable_pages, + gc_stat_size_pool_sym_heap_eden_pages, + gc_stat_size_pool_sym_heap_eden_slots, + gc_stat_size_pool_sym_heap_tomb_pages, + gc_stat_size_pool_sym_heap_tomb_slots, + gc_stat_size_pool_sym_last +}; + +static VALUE gc_stat_size_pool_symbols[gc_stat_size_pool_sym_last]; + +static void +setup_gc_stat_size_pool_symbols(void) +{ + if (gc_stat_size_pool_symbols[0] == 0) { +#define S(s) gc_stat_size_pool_symbols[gc_stat_size_pool_sym_##s] = ID2SYM(rb_intern_const(#s)) + S(slot_size); + S(heap_allocatable_pages); + S(heap_eden_pages); + S(heap_eden_slots); + S(heap_tomb_pages); + S(heap_tomb_slots); +#undef S + } +} + +static size_t +gc_stat_size_pool_internal(int size_pool_idx, VALUE hash_or_sym) +{ + rb_objspace_t *objspace = &rb_objspace; + VALUE hash = Qnil, key = Qnil; + + setup_gc_stat_size_pool_symbols(); + + if (RB_TYPE_P(hash_or_sym, T_HASH)) { + hash = hash_or_sym; + } + else if (SYMBOL_P(hash_or_sym)) { + key = hash_or_sym; + } + else { + rb_raise(rb_eTypeError, "non-hash or symbol argument"); + } + + if (size_pool_idx < 0 || size_pool_idx >= SIZE_POOL_COUNT) { + rb_raise(rb_eArgError, "size pool index out of range"); + } + + rb_size_pool_t *size_pool = &size_pools[size_pool_idx]; + +#define SET(name, attr) \ + if (key == gc_stat_size_pool_symbols[gc_stat_size_pool_sym_##name]) \ + return attr; \ + else if (hash != Qnil) \ + rb_hash_aset(hash, gc_stat_size_pool_symbols[gc_stat_size_pool_sym_##name], SIZET2NUM(attr)); + + SET(slot_size, size_pool->slot_size); + SET(heap_allocatable_pages, size_pool->allocatable_pages); + SET(heap_eden_pages, SIZE_POOL_EDEN_HEAP(size_pool)->total_pages); + SET(heap_eden_slots, SIZE_POOL_EDEN_HEAP(size_pool)->total_slots); + SET(heap_tomb_pages, SIZE_POOL_TOMB_HEAP(size_pool)->total_pages); + SET(heap_tomb_slots, SIZE_POOL_TOMB_HEAP(size_pool)->total_slots); +#undef SET + + if (!NIL_P(key)) { /* matched key should return above */ + rb_raise(rb_eArgError, "unknown key: %"PRIsVALUE, rb_sym2str(key)); + } + + return 0; +} + +static VALUE +gc_stat_size_pool(rb_execution_context_t *ec, VALUE self, VALUE size_pool_idx, VALUE arg) +{ + if (NIL_P(arg)) { + arg = rb_hash_new(); + } + else if (SYMBOL_P(arg)) { + size_t value = gc_stat_internal(arg); + return SIZET2NUM(value); + } + else if (RB_TYPE_P(arg, T_HASH)) { + // ok + } + else { + rb_raise(rb_eTypeError, "non-hash or symbol given"); + } + + gc_stat_size_pool_internal(FIX2INT(size_pool_idx), arg); + + return arg; +} + static VALUE gc_stress_get(rb_execution_context_t *ec, VALUE self) { |