Skip to content

Commit 86d6248

Browse files
committed
growth diag
1 parent 57dc2fa commit 86d6248

1 file changed

Lines changed: 73 additions & 0 deletions

File tree

gc/default/default.c

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,18 @@
139139
#define major_gc_diag(...) (void)0
140140
#endif
141141

142+
/* Logs the heap-growth gate decisions (gc_marks_finish + gc_sweep_finish_heap)
143+
* so a serial vs. parallel-sweep run can be diffed. Compile with
144+
* -DGROWTH_DIAG=1 to enable. */
145+
#ifndef GROWTH_DIAG
146+
#define GROWTH_DIAG 0
147+
#endif
148+
#if GROWTH_DIAG
149+
#define growth_diag(...) fprintf(stderr, __VA_ARGS__)
150+
#else
151+
#define growth_diag(...) (void)0
152+
#endif
153+
142154
#ifndef PSWEEP_LOCK_STATS
143155
#define PSWEEP_LOCK_STATS 0
144156
#endif
@@ -5482,6 +5494,13 @@ gc_sweep_finish_heap(rb_objspace_t *objspace, rb_heap_t *heap)
54825494
}
54835495
#endif
54845496

5497+
#if GROWTH_DIAG
5498+
const char *gd_decision = "no_growth_gate";
5499+
size_t gd_swept_initial = swept_slots;
5500+
size_t gd_alloc_before = objspace->heap_pages.allocatable_bytes;
5501+
size_t gd_resurrected = 0;
5502+
#endif
5503+
54855504
if (swept_slots < min_free_slots &&
54865505
/* The heap is a growth heap if it freed more slots than had empty slots. */
54875506
((heap->empty_slots == 0 && total_slots > 0) || heap->freed_slots > heap->empty_slots)) {
@@ -5496,6 +5515,10 @@ gc_sweep_finish_heap(rb_objspace_t *objspace, rb_heap_t *heap)
54965515
heap_add_freepage(heap, resurrected_page, "gc_sweep_finish_heap");
54975516

54985517
swept_slots += resurrected_page->free_slots;
5518+
#if GROWTH_DIAG
5519+
gd_resurrected++;
5520+
gd_decision = "resurrect";
5521+
#endif
54995522
}
55005523

55015524
if (swept_slots < min_free_slots) {
@@ -5505,15 +5528,32 @@ gc_sweep_finish_heap(rb_objspace_t *objspace, rb_heap_t *heap)
55055528
objspace->profile.count - objspace->rgengc.last_major_gc < RVALUE_OLD_AGE) {
55065529
if (objspace->heap_pages.allocatable_bytes < min_free_slots * heap->slot_size) {
55075530
heap_allocatable_bytes_expand(objspace, heap, swept_slots, heap->total_slots, heap->slot_size);
5531+
#if GROWTH_DIAG
5532+
gd_decision = "expand";
5533+
#endif
55085534
}
55095535
}
55105536
else if (swept_slots < min_free_slots * 7 / 8 &&
55115537
objspace->heap_pages.allocatable_bytes < (min_free_slots * 7 / 8 - swept_slots) * heap->slot_size) {
55125538
gc_needs_major_flags |= GPR_FLAG_MAJOR_BY_NOFREE;
55135539
heap->force_major_gc_count++;
5540+
#if GROWTH_DIAG
5541+
gd_decision = "force_major_nofree";
5542+
#endif
55145543
}
55155544
}
55165545
}
5546+
5547+
growth_diag("[growth_diag] site=sweep_finish_heap psweep=%d heap=%d reason=0x%x count=%zu "
5548+
"since_major=%zd full_mark=%d total_slots=%zu swept=%zu(freed=%zu+empty=%zu) "
5549+
"min_free=%zu alloc_bytes=%zu->%zu resurrected=%zu decision=%s\n",
5550+
USE_PARALLEL_SWEEP, (int)(heap - heaps), objspace->profile.latest_gc_info,
5551+
objspace->profile.count,
5552+
(ssize_t)(objspace->profile.count - objspace->rgengc.last_major_gc),
5553+
is_full_marking(objspace), total_slots, gd_swept_initial,
5554+
heap->freed_slots, heap->empty_slots, min_free_slots,
5555+
gd_alloc_before, objspace->heap_pages.allocatable_bytes,
5556+
gd_resurrected, gd_decision);
55175557
}
55185558

55195559
static void
@@ -7542,14 +7582,35 @@ gc_marks_finish(rb_objspace_t *objspace)
75427582
heap_pages_freeable_pages = 0;
75437583
}
75447584

7585+
#if GROWTH_DIAG
7586+
const char *gd_decision;
7587+
int gd_full_entry = full_marking;
7588+
size_t gd_alloc_before = objspace->heap_pages.allocatable_bytes;
7589+
if (objspace->heap_pages.allocatable_bytes != 0) {
7590+
gd_decision = "closed:alloc_bytes_nonzero";
7591+
}
7592+
else if (sweep_slots >= min_free_slots) {
7593+
gd_decision = "closed:enough_free";
7594+
}
7595+
else {
7596+
gd_decision = "open:noop";
7597+
}
7598+
#endif
7599+
75457600
if (objspace->heap_pages.allocatable_bytes == 0 && sweep_slots < min_free_slots) {
75467601
if (!full_marking && sweep_slots < min_free_slots * 7 / 8) {
75477602
if (objspace->profile.count - objspace->rgengc.last_major_gc < RVALUE_OLD_AGE) {
75487603
full_marking = TRUE;
7604+
#if GROWTH_DIAG
7605+
gd_decision = "promote_to_full";
7606+
#endif
75497607
}
75507608
else {
75517609
gc_report(1, objspace, "gc_marks_finish: next is full GC!!)\n");
75527610
gc_needs_major_flags |= GPR_FLAG_MAJOR_BY_NOFREE;
7611+
#if GROWTH_DIAG
7612+
gd_decision = "force_major_nofree";
7613+
#endif
75537614
}
75547615
}
75557616

@@ -7562,9 +7623,21 @@ gc_marks_finish(rb_objspace_t *objspace)
75627623
/*size_t avg_slot_size = total_slots > 0 ? total_heap_bytes / total_slots : (size_t)heaps[0].slot_size;*/
75637624
/*heap_allocatable_bytes_expand(objspace, NULL, sweep_slots, total_slots, avg_slot_size);*/
75647625
heap_allocatable_bytes_expand(objspace, NULL, sweep_slots, total_slots, heaps[0].slot_size);
7626+
#if GROWTH_DIAG
7627+
if (gd_full_entry) gd_decision = "expand";
7628+
#endif
75657629
}
75667630
}
75677631

7632+
growth_diag("[growth_diag] site=marks_finish psweep=%d reason=0x%x count=%zu since_major=%zd "
7633+
"full_mark=%d total_slots=%zu sweep_slots=%zu min_free=%zu max_free=%zu "
7634+
"freeable_pages=%zu alloc_bytes=%zu->%zu decision=%s\n",
7635+
USE_PARALLEL_SWEEP, objspace->profile.latest_gc_info, objspace->profile.count,
7636+
(ssize_t)(objspace->profile.count - objspace->rgengc.last_major_gc),
7637+
gd_full_entry, total_slots, sweep_slots, min_free_slots, max_free_slots,
7638+
heap_pages_freeable_pages, gd_alloc_before, objspace->heap_pages.allocatable_bytes,
7639+
gd_decision);
7640+
75687641
if (full_marking) {
75697642
/* See the comment about RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR */
75707643
const double r = gc_params.oldobject_limit_factor;

0 commit comments

Comments
 (0)