From 6957780cd5775f410623a1155e531a9584050060 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Sat, 19 Dec 2015 10:17:39 -0700 Subject: [PATCH] incremental GC: tune departure from incremental mode At the completion of an incremental major GC, if incremental mode wasn't requested recently, schedule an immediate major GC to reduce the heap back to its normal footprint. --- racket/src/racket/gc2/newgc.c | 30 ++++++++++++++++++++++-------- racket/src/racket/gc2/newgc.h | 2 +- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/racket/src/racket/gc2/newgc.c b/racket/src/racket/gc2/newgc.c index 25ce68c1dd..5821c24c63 100644 --- a/racket/src/racket/gc2/newgc.c +++ b/racket/src/racket/gc2/newgc.c @@ -3666,7 +3666,10 @@ void GC_request_incremental_mode(void) { NewGC *gc = GC_get_GC(); - gc->incremental_requested = 1; + /* The request will expire gradually, so that an extra major GC will + be triggered if incremental mode hasn't been requested recently + enough: */ + gc->incremental_requested = 8; } void GC_set_incremental_mode(int on) @@ -6091,7 +6094,7 @@ static void garbage_collect(NewGC *gc, int force_full, int no_full, int switchin uintptr_t old_gen0; uintptr_t old_mem_allocated; int next_gc_full; - int do_incremental = 0, check_inc_repair; + int do_incremental = 0, had_started_incremental, check_inc_repair; old_mem_use = gc->memory_in_use; /* includes gc->phantom_count */ old_gen0 = gen0_size_in_use(gc) + gc->gen0_phantom_count; @@ -6114,7 +6117,7 @@ static void garbage_collect(NewGC *gc, int force_full, int no_full, int switchin fraction of the actual use by live data: */ || (gc->memory_in_use > (FULL_COLLECTION_SIZE_RATIO * gc->last_full_mem_use - * (gc->started_incremental + * (gc->incremental_requested ? INCREMENTAL_EXTRA_SIZE_RATIO : 1))) /* Just in case, for a full GC every so often, unless @@ -6134,7 +6137,7 @@ static void garbage_collect(NewGC *gc, int force_full, int no_full, int switchin return; next_gc_full = (gc->gc_full - && !gc->started_incremental + && !gc->incremental_requested && !gc->full_needed_for_finalization); if (gc->full_needed_for_finalization && gc->gc_full) @@ -6178,7 +6181,8 @@ static void garbage_collect(NewGC *gc, int force_full, int no_full, int switchin if (do_incremental) gc->started_incremental = 1; - gc->incremental_requested = 0; + if (gc->incremental_requested) + --gc->incremental_requested; gc->mark_gen1 = (gc->gc_full || gc->started_incremental) && !gc->all_marked_incremental; gc->check_gen1 = gc->gc_full && !gc->all_marked_incremental; @@ -6384,12 +6388,14 @@ static void garbage_collect(NewGC *gc, int force_full, int no_full, int switchin else gc->since_last_full += 10; } + had_started_incremental = gc->started_incremental; if (gc->gc_full) { gc->last_full_mem_use = gc->memory_in_use; gc->started_incremental = 0; gc->all_marked_incremental = 0; gc->finished_incremental = 0; gc->inc_prop_count = 0; + gc->incremental_requested = 0; /* request expires completely after a full GC */ } /* inform the system (if it wants us to) that we're done with collection */ @@ -6401,7 +6407,7 @@ static void garbage_collect(NewGC *gc, int force_full, int no_full, int switchin is_master = (gc == MASTERGC); #endif park_for_inform_callback(gc); - gc->GC_collect_inform_callback(is_master, gc->gc_full, gc->started_incremental, + gc->GC_collect_inform_callback(is_master, gc->gc_full, had_started_incremental, /* original memory use: */ old_mem_use + old_gen0, /* new memory use; gen0_phantom_count can be non-zero due to @@ -6435,8 +6441,16 @@ static void garbage_collect(NewGC *gc, int force_full, int no_full, int switchin if (gc->gc_full) merge_run_queues(gc); - if (!gc->run_queue) - next_gc_full = 0; + if (!gc->run_queue) { + if (had_started_incremental) { + /* Keep next_gc_full, if it's set, because that means incremental + mode wasn't requested recently, even through we're wrapping up + an incremental GC; another major GC is likely to reclaim more + memory, reduce fragentation, and generally improve heap + health */ + } else + next_gc_full = 0; + } /* Run any queued finalizers, EXCEPT in the case where this collection was triggered during the execution of a finalizer. diff --git a/racket/src/racket/gc2/newgc.h b/racket/src/racket/gc2/newgc.h index 973eeb3dec..76215402f4 100644 --- a/racket/src/racket/gc2/newgc.h +++ b/racket/src/racket/gc2/newgc.h @@ -228,7 +228,7 @@ typedef struct NewGC { unsigned char inc_gen1 :1; /* during incremental marking of old generation */ unsigned char fnl_gen1 :1; /* during incremental finalization of old generation */ unsigned char during_backpointer :1; - unsigned char incremental_requested :1; + unsigned char incremental_requested :4; /* counts down to track recentness of request */ unsigned char high_fragmentation :1; unsigned char unprotected_page :1;