aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Zhu <peter@peterzhu.ca>2022-07-20 13:29:34 -0400
committerPeter Zhu <peter@peterzhu.ca>2022-07-21 10:46:32 -0400
commitcdbb9b8555b4ddcc4c557f25ad785cae6209478d (patch)
tree00a23b3f4ca696b031cc826a5fc17f87f1b2b14c
parent804b073573eb180f12e77a0e3840f04d6eac86aa (diff)
downloadruby-cdbb9b8555b4ddcc4c557f25ad785cae6209478d.tar.gz
[Bug #18929] Fix heap creation thrashing in GC
Before this commit, if we don't have enough slots after sweeping but had pages on the tomb heap, then the GC would frequently allocate and deallocate pages. This is because after sweeping it would set allocatable pages (since there were not enough slots) but free the pages on the tomb heap. This commit reuses pages on the tomb heap if there's not enough slots after sweeping.
-rw-r--r--gc.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/gc.c b/gc.c
index 4f92c371be..4b619fd33f 100644
--- a/gc.c
+++ b/gc.c
@@ -5810,6 +5810,19 @@ gc_sweep_finish_size_pool(rb_objspace_t *objspace, rb_size_pool_t *size_pool)
min_free_slots = gc_params.heap_init_slots;
}
+ /* If we don't have enough slots and we have pages on the tomb heap, move
+ * pages from the tomb heap to the eden heap. This may prevent page
+ * creation thrashing (frequently allocating and deallocting pages) and
+ * GC thrashing (running GC more frequently than required). */
+ struct heap_page *resurrected_page;
+ while (swept_slots < min_free_slots &&
+ (resurrected_page = heap_page_resurrect(objspace, size_pool))) {
+ swept_slots += resurrected_page->free_slots;
+
+ heap_add_page(objspace, size_pool, heap, resurrected_page);
+ heap_add_freepage(heap, resurrected_page);
+ }
+
if (swept_slots < min_free_slots) {
bool grow_heap = is_full_marking(objspace);