~ chicken-core (chicken-5) 5a3f3638fe6fa7fb86fb8eea591e103db4420d1f
commit 5a3f3638fe6fa7fb86fb8eea591e103db4420d1f Author: Peter Bex <peter@more-magic.net> AuthorDate: Sun Apr 19 14:50:04 2015 +0200 Commit: Peter Bex <peter@more-magic.net> CommitDate: Sun May 31 14:55:25 2015 +0200 Use precise tracking of scratch space memory usage to reduce the number of "forced" minor GCs diff --git a/chicken.h b/chicken.h index 2ffd81d7..4595a75f 100644 --- a/chicken.h +++ b/chicken.h @@ -1217,8 +1217,6 @@ extern double trunc(double); * stack or reclaim, but in a clever way so it's only done at the * "end" of a C function. */ -#define C_scratch_usage (C_scratchspace_top - C_scratchspace_start) - #if C_STACK_GROWS_DOWNWARD # define C_demand(n) (C_stress && ((C_word)(C_stack_pointer - C_stack_limit) > ((n)+C_scratch_usage))) # define C_stack_probe(p) (C_stress && (((C_word *)(p)-C_scratch_usage) >= C_stack_limit)) @@ -1767,6 +1765,7 @@ C_varextern C_TLS C_word *C_scratchspace_start, *C_scratchspace_top, *C_scratchspace_limit, + C_scratch_usage, C_bignum_type_tag, C_ratnum_type_tag, C_cplxnum_type_tag; diff --git a/runtime.c b/runtime.c index 4c86e228..99fe2034 100644 --- a/runtime.c +++ b/runtime.c @@ -336,6 +336,7 @@ C_TLS C_word *C_scratchspace_start, *C_scratchspace_top, *C_scratchspace_limit, + C_scratch_usage, C_bignum_type_tag, C_ratnum_type_tag, C_cplxnum_type_tag; @@ -829,6 +830,7 @@ int CHICKEN_initialize(int heap, int stack, int symbols, void *toplevel) C_scratchspace_start = NULL; C_scratchspace_top = NULL; C_scratchspace_limit = NULL; + C_scratch_usage = 0; scratchspace_size = 0; live_finalizer_count = 0; allocated_finalizer_count = 0; @@ -2904,13 +2906,13 @@ C_regparm C_word C_fcall C_scratch_alloc(C_uword size) if (C_scratchspace_top + size + 2 >= C_scratchspace_limit) { C_word *new_scratch_start, *new_scratch_top, *new_scratch_limit; - C_uword needed = scratchspace_size + size + 2, - new_size = nmax(scratchspace_size, DEFAULT_SCRATCH_SPACE_SIZE); + C_uword needed = C_scratch_usage + size + 2, + new_size = nmax(scratchspace_size << 1, 2UL << C_ilen(needed)); - /* Increase by a factor of 2^n so we can store the requested size */ - while (new_size < needed) new_size <<= 1; + /* Shrink if the needed size is much smaller, but not below minimum */ + if (needed < (new_size >> 4)) new_size >>= 1; + new_size = nmax(new_size, DEFAULT_SCRATCH_SPACE_SIZE); - scratchspace_realloc: /* TODO: Maybe we should work with two semispaces to reduce mallocs? */ new_scratch_start = (C_word *)C_malloc(C_wordstobytes(new_size)); if (new_scratch_start == NULL) @@ -2992,14 +2994,9 @@ C_regparm C_word C_fcall C_scratch_alloc(C_uword size) C_scratchspace_start = new_scratch_start; C_scratchspace_top = new_scratch_top; C_scratchspace_limit = new_scratch_limit; + /* Scratch space is now tightly packed */ + C_scratch_usage = (new_scratch_top - new_scratch_start); scratchspace_size = new_size; - - needed = nmax(C_scratch_usage + size + 2, DEFAULT_SCRATCH_SPACE_SIZE); - /* Allow scratch space to shrink if we go below an eighth of its usage */ - if (needed < (new_size >> 3)) { - new_size = nmax(new_size >> 2, DEFAULT_SCRATCH_SPACE_SIZE); - goto scratchspace_realloc; - } } assert(C_scratchspace_top + size + 2 <= C_scratchspace_limit); @@ -3007,6 +3004,8 @@ C_regparm C_word C_fcall C_scratch_alloc(C_uword size) *(C_scratchspace_top+1) = (C_word)NULL; /* Nothing points here 'til mutated */ result = (C_word)(C_scratchspace_top+2); C_scratchspace_top += size + 2; + /* This will only be marked as "used" when it's claimed by a pointer */ + /* C_scratch_usage += size + 2; */ return result; } @@ -3062,7 +3061,10 @@ C_migrate_buffer_object(C_word **ptr, C_word *start, C_word *end, C_word obj) C_word *sp = (C_word *)slot; if (*(sp-1) == ALIGNMENT_HOLE_MARKER) --sp; + if (*(sp-1) != (C_word)NULL && p == NULL) + C_scratch_usage -= *(sp-2) + 2; *(sp-1) = (C_word)p; /* This is why we traverse even if p = NULL */ + *data = C_SCHEME_UNBOUND; /* Ensure old reference is killed dead */ } } else { /* Slot is not a scratchspace object: check sub-objects */ @@ -3087,6 +3089,10 @@ C_regparm C_word C_fcall C_mutate_scratch_slot(C_word *slot, C_word val) assert(C_in_scratchspacep(val)); assert(slot == NULL || C_in_stackp((C_word)slot)); if (*(ptr-1) == ALIGNMENT_HOLE_MARKER) --ptr; + if (*(ptr-1) == (C_word)NULL && slot != NULL) + C_scratch_usage += *(ptr-2) + 2; + if (*(ptr-1) != (C_word)NULL && slot == NULL) + C_scratch_usage -= *(ptr-2) + 2; *(ptr-1) = (C_word)slot; /* Remember the slot pointing here, for realloc */ if (slot != NULL) *slot = val; return val; @@ -3455,6 +3461,7 @@ C_regparm void C_fcall C_reclaim(void *trampoline, void *proc) C_scratchspace_start = NULL; C_scratchspace_top = NULL; C_scratchspace_limit = NULL; + C_scratch_usage = 0; scratchspace_size = 0; }Trap