summaryrefslogtreecommitdiff
path: root/gc.c
diff options
context:
space:
mode:
authorPeter Zhu <peter@peterzhu.ca>2021-11-25 09:31:58 -0500
committerPeter Zhu <peter@peterzhu.ca>2021-11-25 10:33:17 -0500
commit6157619bb68e4307cdf065cb73d5bfcec30d042d (patch)
treed0fff7d4c5bae8809eb6bafebbf567fa30b4dcdc /gc.c
parent09ef048b34dd4aed65ec2899315a91d25ffa7629 (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.c95
1 files changed, 95 insertions, 0 deletions
diff --git a/gc.c b/gc.c
index e0ba25860c..3b94e8ded0 100644
--- a/gc.c
+++ b/gc.c
@@ -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)
{