~ chicken-core (chicken-5) 4caae1f300fca261443c2c13f37edeed79538ac9
commit 4caae1f300fca261443c2c13f37edeed79538ac9 Author: megane <meganeka@gmail.com> AuthorDate: Sun Mar 29 10:10:14 2020 +1300 Commit: Peter Bex <peter@more-magic.net> CommitDate: Mon Apr 13 14:11:48 2020 +0200 Prevent excessive major gcs by preserving a decent amount of unused heap Signed-off-by: Evan Hanson <evhan@foldling.org> Signed-off-by: Peter Bex <peter@more-magic.net> diff --git a/NEWS b/NEWS index 825fa8ab..6abd273e 100644 --- a/NEWS +++ b/NEWS @@ -9,8 +9,12 @@ - Sleeping primordial thread doesn't forget mutations made to parameters in interrupt handlers anymore. (See #1638. Fix contributed by Sebastien Marie) -- A feature corresponding to the word size is available - regardless of the word size (#1693) + - A feature corresponding to the word size is available + regardless of the word size (#1693) + - A new runtime flag `-:hf' was added, which controls the minimum + free heap space at which garbage collector will increase the heap + size. This is set to 4M by default to prevent excessive + major GCs when the heap hovers around being almost full. - Build system - Auto-configure at build time on most platforms. Cross-compilation diff --git a/manual/Using the compiler b/manual/Using the compiler index fd656362..7a96920a 100644 --- a/manual/Using the compiler +++ b/manual/Using the compiler @@ -223,6 +223,8 @@ by the startup code and will not be contained in the result of ; {{-:hmNUMBER}} : Specifies a maximal heap size (including both semispaces). The default is (2GB - 15). +; {{-:hfNUMBER}} : Specifies the minimum avilable heap space. If the free space (in one semispace) is less than this number (4MB by default), then the heap is grown. + ; {{-:hsPERCENTAGE}} : Sets the shrink rate of the heap in percent. The heap is shrunk to {{PERCENTAGE}} when the watermark is reached. The default is 50. Note: If you want to make sure that the heap never shrinks, specify a value of {{0}}. (this can be useful in situations where an optimal heap-size is known in advance). ; {{-:huPERCENTAGE}} : Sets the memory usage watermark below which heap shrinking is triggered. The default is 25. diff --git a/runtime.c b/runtime.c index 8e049623..b285b4f2 100644 --- a/runtime.c +++ b/runtime.c @@ -163,6 +163,7 @@ static C_TLS int timezone; #define DEFAULT_HEAP_GROWTH 200 #define DEFAULT_HEAP_SHRINKAGE 50 #define DEFAULT_HEAP_SHRINKAGE_USED 25 +#define DEFAULT_HEAP_MIN_FREE (4 * 1024 * 1024) #define DEFAULT_FORWARDING_TABLE_SIZE 32 #define DEFAULT_LOCATIVE_TABLE_SIZE 32 #define DEFAULT_COLLECTIBLES_SIZE 1024 @@ -360,6 +361,7 @@ C_TLS C_uword C_heap_growth = DEFAULT_HEAP_GROWTH, C_heap_shrinkage = DEFAULT_HEAP_SHRINKAGE, C_heap_shrinkage_used = DEFAULT_HEAP_SHRINKAGE_USED, + C_heap_min_free = DEFAULT_HEAP_MIN_FREE, C_maximal_heap_size = DEFAULT_MAXIMAL_HEAP_SIZE; C_TLS time_t C_startup_time_seconds, @@ -1362,6 +1364,7 @@ void CHICKEN_parse_command_line(int argc, char *argv[], C_word *heap, C_word *st " -:o disable stack overflow checks\n" " -:hiSIZE set initial heap size\n" " -:hmSIZE set maximal heap size\n" + " -:hfSIZE set minimum unused heap size\n" " -:hgPERCENTAGE set heap growth percentage\n" " -:hsPERCENTAGE set heap shrink percentage\n" " -:huPERCENTAGE set percentage of memory used at which heap will be shrunk\n" @@ -1390,6 +1393,9 @@ void CHICKEN_parse_command_line(int argc, char *argv[], C_word *heap, C_word *st *heap = arg_val(ptr + 1); heap_size_changed = 1; goto next; + case 'f': + C_heap_min_free = arg_val(ptr + 1); + goto next; case 'g': C_heap_growth = arg_val(ptr + 1); goto next; @@ -3605,7 +3611,7 @@ C_regparm void C_fcall C_reclaim(void *trampoline, C_word c) /*** isn't gc_mode always GC_MAJOR here? */ /* NOTE: count is actual usage, heap_size is both halves */ if(gc_mode == GC_MAJOR && - count < percentage(heap_size/2, C_heap_shrinkage_used) && + C_heap_min_free + count < percentage(heap_size / 2, C_heap_shrinkage_used) && C_heap_shrinkage > 0 && heap_size > MINIMAL_HEAP_SIZE && !C_heap_size_is_fixed) C_rereclaim2(percentage(heap_size, C_heap_shrinkage), 0); @@ -3809,7 +3815,8 @@ C_regparm void C_fcall really_mark(C_word *x) n = C_header_size(p); bytes = (h & C_BYTEBLOCK_BIT) ? n : n * sizeof(C_word); - if(((C_byte *)p2 + bytes + sizeof(C_word)) > tospace_limit) { + /* Check for needed size plus minimum unused block: */ + if(((C_byte *)p2 + bytes + sizeof(C_word) + C_heap_min_free) > tospace_limit) { /* Detect impossibilities before GC_REALLOC to preserve state: */ if (C_in_stackp((C_word)p) && bytes > stack_size) panic(C_text("Detected corrupted data in stack"));Trap