Feature #7457
closedGC.stat to return "allocated object count" and "freed object count"
Description
How about to return "allocated object count" and "freed object count"?
The following patch enable to show "total allocated object number"
and "total freed (deallocated) object number".
pp GC.stat #=>
{:count=>0,
:heap_used=>12,
:heap_length=>12,
:heap_increment=>0,
:heap_live_num=>7494,
:heap_free_num=>0,
:heap_final_num=>0,
:heap_allocated_num=>7585, # <= new one!
:heap_freed_num=>88} # <= new one!
Maybe performance has mostly no impact with this patch.
Exact live object number can be calculated by "heap_allocated_num - heap_freed_num".
These values will be overflow. So they are only hint of performance tuning.
Index: gc.c¶
--- gc.c (revision 37946)
+++ gc.c (working copy)
@@ -225,7 +225,8 @@ typedef struct rb_objspace {
struct heaps_free_bitmap *free_bitmap;
RVALUE *range[2];
struct heaps_header *freed;
- size_t live_num;
- size_t allocated_num;
- size_t freed_num;
size_t free_num;
size_t free_min;
size_t final_num;
@@ -352,8 +353,6 @@ static inline void gc_prof_mark_timer_st
static inline void gc_prof_sweep_timer_start(rb_objspace_t *);
static inline void gc_prof_sweep_timer_stop(rb_objspace_t *);
static inline void gc_prof_set_malloc_info(rb_objspace_t *);
-static inline void gc_prof_inc_live_num(rb_objspace_t *);
-static inline void gc_prof_dec_live_num(rb_objspace_t *);
/*
@@ -531,7 +530,6 @@ assign_heap_slot(rb_objspace_t *objspace
objspace->heap.sorted[hi]->bits = (uintptr_t *)objspace->heap.free_bitmap;
objspace->heap.free_bitmap = objspace->heap.free_bitmap->next;
memset(heaps->bits, 0, HEAP_BITMAP_LIMIT * sizeof(uintptr_t));
- objspace->heap.free_num += objs;
pend = p + objs;
if (lomem == 0 || lomem > p) lomem = p;
if (himem < pend) himem = pend;
@@ -660,7 +658,7 @@ newobj(VALUE klass, VALUE flags)
RANY(obj)->file = rb_sourcefile();
RANY(obj)->line = rb_sourceline();
#endif - gc_prof_inc_live_num(objspace);
-
objspace->heap.allocated_num++;
return obj;
}
@@ -1422,7 +1420,8 @@ finalize_list(rb_objspace_t objspace, R
if (!FL_TEST(p, FL_SINGLETON)) { / not freeing page */
add_slot_local_freelist(objspace, p);
if (!is_lazy_sweeping(objspace)) {
-
gc_prof_dec_live_num(objspace);
-
objspace->heap.freed_num++;
-
}objspace->heap.free_num++; }
else {
@@ -1873,10 +1872,16 @@ gc_clear_slot_bits(struct heaps_slot *sl
memset(slot->bits, 0, HEAP_BITMAP_LIMIT * sizeof(uintptr_t));
}
+static size_t
+objspace_live_num(rb_objspace_t *objspace)
+{
- return objspace->heap.allocated_num - objspace->heap.freed_num;
+}
static void
slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot)
{
- size_t free_num = 0, final_num = 0;
- size_t empty_num = 0, freed_num = 0, final_num = 0;
RVALUE *p, *pend;
RVALUE *final = deferred_final_list;
int deferred;
@@ -1903,17 +1908,17 @@ slot_sweep(rb_objspace_t *objspace, stru
p->as.free.flags = 0;
p->as.free.next = sweep_slot->freelist;
sweep_slot->freelist = p;
-
free_num++;
-
freed_num++; } } else {
-
free_num++;
-
}empty_num++; } } p++;
gc_clear_slot_bits(sweep_slot);
- if (final_num + free_num == sweep_slot->header->limit &&
- if (final_num + freed_num + empty_num == sweep_slot->header->limit &&
objspace->heap.free_num > objspace->heap.do_heap_free) {
RVALUE *pp;
@@ -1925,13 +1930,14 @@ slot_sweep(rb_objspace_t *objspace, stru
unlink_heap_slot(objspace, sweep_slot);
}
else {
-
if (free_num > 0) {
-
if (freed_num + empty_num > 0) { link_free_heap_slot(objspace, sweep_slot); } else { sweep_slot->free_next = NULL; }
-
objspace->heap.free_num += free_num;
- objspace->heap.freed_num += freed_num;
- objspace->heap.free_num += freed_num + empty_num;
}
objspace->heap.final_num += final_num;
@@ -1990,7 +1996,8 @@ after_gc_sweep(rb_objspace_t *objspace)
inc = ATOMIC_SIZE_EXCHANGE(malloc_increase, 0);
if (inc > malloc_limit) {
- malloc_limit += (size_t)((inc - malloc_limit) * (double)objspace->heap.live_num / (heaps_used * HEAP_OBJ_LIMIT));
- malloc_limit +=
-
if (malloc_limit < initial_malloc_limit) malloc_limit = initial_malloc_limit;(size_t)((inc - malloc_limit) * (double)objspace_live_num(objspace) / (heaps_used * HEAP_OBJ_LIMIT));
}
@@ -2063,7 +2070,7 @@ gc_prepare_free_objects(rb_objspace_t *o
gc_marks(objspace);
before_gc_sweep(objspace);
- if (objspace->heap.free_min > (heaps_used * HEAP_OBJ_LIMIT - objspace->heap.live_num)) {
- if (objspace->heap.free_min > (heaps_used * HEAP_OBJ_LIMIT - objspace_live_num(objspace))) {
set_heaps_increment(objspace);
}
@@ -2544,7 +2551,6 @@ gc_mark_ptr(rb_objspace_t *objspace, VAL
register uintptr_t *bits = GET_HEAP_BITMAP(ptr);
if (MARKED_IN_BITMAP(bits, ptr)) return 0;
MARK_IN_BITMAP(bits, ptr);
- objspace->heap.live_num++;
return 1;
}
@@ -2905,11 +2911,8 @@ gc_marks(rb_objspace_t *objspace)
objspace->mark_func_data = 0;
gc_prof_mark_timer_start(objspace);
-
objspace->heap.live_num = 0;
objspace->count++; -
SET_STACK_END;
th->vm->self ? rb_gc_mark(th->vm->self) : rb_vm_mark(th->vm);
@@ -2956,7 +2959,8 @@ rb_gc_force_recycle(VALUE p)
add_slot_local_freelist(objspace, (RVALUE *)p);
}
else { -
gc_prof_dec_live_num(objspace);
- objspace->heap.freed_num++;
- objspace->heap.free_num++;
slot = add_slot_local_freelist(objspace, (RVALUE *)p);
if (slot->free_next == NULL) {
link_free_heap_slot(objspace, slot);
@@ -3172,9 +3176,11 @@ gc_stat(int argc, VALUE *argv, VALUE sel
rb_hash_aset(hash, ID2SYM(rb_intern("heap_used")), SIZET2NUM(objspace->heap.used));
rb_hash_aset(hash, ID2SYM(rb_intern("heap_length")), SIZET2NUM(objspace->heap.length));
rb_hash_aset(hash, ID2SYM(rb_intern("heap_increment")), SIZET2NUM(objspace->heap.increment));
- rb_hash_aset(hash, ID2SYM(rb_intern("heap_live_num")), SIZET2NUM(objspace->heap.live_num));
- rb_hash_aset(hash, ID2SYM(rb_intern("heap_live_num")), SIZET2NUM(objspace_live_num(objspace)));
rb_hash_aset(hash, ID2SYM(rb_intern("heap_free_num")), SIZET2NUM(objspace->heap.free_num));
rb_hash_aset(hash, ID2SYM(rb_intern("heap_final_num")), SIZET2NUM(objspace->heap.final_num)); - rb_hash_aset(hash, ID2SYM(rb_intern("heap_allocated_num")), SIZET2NUM(objspace->heap.allocated_num));
- rb_hash_aset(hash, ID2SYM(rb_intern("heap_freed_num")), SIZET2NUM(objspace->heap.freed_num));
return hash;
}
@@ -3952,7 +3958,7 @@ gc_prof_set_malloc_info(rb_objspace_t *o
static inline void
gc_prof_set_heap_info(rb_objspace_t *objspace, gc_profile_record *record)
{
- size_t live = objspace->heap.live_num;
-
size_t live = objspace_live_num(objspace);
size_t total = heaps_used * HEAP_OBJ_LIMIT;record->heap_total_objects = total;
@@ -3960,16 +3966,6 @@ gc_prof_set_heap_info(rb_objspace_t *obj
record->heap_total_size = total * sizeof(RVALUE);
}
-static inline void
-gc_prof_inc_live_num(rb_objspace_t *objspace)
-{
-}
-static inline void
-gc_prof_dec_live_num(rb_objspace_t *objspace)
-{
-}
#else
static inline void
@@ -4057,18 +4053,6 @@ gc_prof_set_heap_info(rb_objspace_t *obj
record->have_finalize = deferred_final_list ? Qtrue : Qfalse;
record->heap_use_size = live * sizeof(RVALUE);
record->heap_total_size = total * sizeof(RVALUE);
-}
-static inline void
-gc_prof_inc_live_num(rb_objspace_t *objspace)
-{
- objspace->heap.live_num++;
-}
-static inline void
-gc_prof_dec_live_num(rb_objspace_t *objspace)
-{
- objspace->heap.live_num--;
}
#endif /* !GC_PROFILE_MORE_DETAIL */