summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Valentine-House <matt@eightbitraptor.com>2026-03-31 13:05:25 +0100
committerMatt Valentine-House <matt@eightbitraptor.com>2026-04-09 13:24:09 +0100
commita8009c9843dcbd742190700b59464e971236a55e (patch)
tree157b5604e0b56fe6e6058cb3c759d046d1643db3
parent5c968c5078f87e539f72712fecefc61f53a6ff29 (diff)
Allow flex in heap growth threshold
Add a 7/8 multiplier to the min_free_slots checks in gc_sweep_finish_heap and gc_marks_finish, allowing heaps to be up to ~12.5% below the free slots target without triggering a major GC or forced growth. With 12 heaps instead of 5, each heap independently hitting the exact threshold would cause excessive memory growth. The slack prevents cascading growth decisions while still ensuring heaps stay close to their target occupancy.
-rw-r--r--gc/default/default.c5
1 files changed, 3 insertions, 2 deletions
diff --git a/gc/default/default.c b/gc/default/default.c
index 5f008b44a1..7bad68f902 100644
--- a/gc/default/default.c
+++ b/gc/default/default.c
@@ -3870,7 +3870,8 @@ gc_sweep_finish_heap(rb_objspace_t *objspace, rb_heap_t *heap)
heap_allocatable_bytes_expand(objspace, heap, swept_slots, heap->total_slots, heap->slot_size);
}
}
- else if (objspace->heap_pages.allocatable_bytes < (min_free_slots - swept_slots) * heap->slot_size) {
+ else if (swept_slots < min_free_slots * 7 / 8 &&
+ objspace->heap_pages.allocatable_bytes < (min_free_slots * 7 / 8 - swept_slots) * heap->slot_size) {
gc_needs_major_flags |= GPR_FLAG_MAJOR_BY_NOFREE;
heap->force_major_gc_count++;
}
@@ -5500,7 +5501,7 @@ gc_marks_finish(rb_objspace_t *objspace)
}
if (objspace->heap_pages.allocatable_bytes == 0 && sweep_slots < min_free_slots) {
- if (!full_marking) {
+ if (!full_marking && sweep_slots < min_free_slots * 7 / 8) {
if (objspace->profile.count - objspace->rgengc.last_major_gc < RVALUE_OLD_AGE) {
full_marking = TRUE;
}