tweaks for fixed-size heaps, fix issue #632

This commit is contained in:
Alex Shinn 2020-05-11 10:43:36 +09:00
parent 90b0336048
commit 83e82f55a7
4 changed files with 56 additions and 9 deletions

51
gc.c
View file

@ -37,12 +37,14 @@ static sexp_heap sexp_heap_last (sexp_heap h) {
return h;
}
#if !SEXP_USE_FIXED_CHUNK_SIZE_HEAPS
static size_t sexp_heap_total_size (sexp_heap h) {
size_t total_size = 0;
for (; h; h=h->next)
total_size += h->size;
return total_size;
}
#endif
#if ! SEXP_USE_GLOBAL_HEAP
#if SEXP_USE_DEBUG_GC
@ -571,26 +573,38 @@ int sexp_grow_heap (sexp ctx, size_t size, size_t chunk_size) {
#if SEXP_USE_FIXED_CHUNK_SIZE_HEAPS
for (tmp=sexp_context_heap(ctx); tmp; tmp=tmp->next)
if (tmp->chunk_size == size) {
while (tmp->next && tmp->next->chunk_size == size)
tmp = tmp->next;
h = tmp;
chunk_size = size;
break;
}
#endif
cur_size = h->size;
new_size = sexp_heap_align(((cur_size > size) ? cur_size : size) * 2);
new_size = (size_t) ceil(SEXP_GROW_HEAP_FACTOR * (double) (sexp_heap_align(((cur_size > size) ? cur_size : size))));
tmp = sexp_make_heap(new_size, h->max_size, chunk_size);
if (tmp) tmp->next = h->next;
h->next = tmp;
if (tmp) {
tmp->next = h->next;
h->next = tmp;
}
return (h->next != NULL);
}
void* sexp_try_alloc (sexp ctx, size_t size) {
sexp_free_list ls1, ls2, ls3;
sexp_heap h;
#if SEXP_USE_FIXED_CHUNK_SIZE_HEAPS
int found_fixed = 0;
#endif
for (h=sexp_context_heap(ctx); h; h=h->next) {
#if SEXP_USE_FIXED_CHUNK_SIZE_HEAPS
if (h->chunk_size && h->chunk_size != size)
continue;
if (h->chunk_size) {
if (h->chunk_size != size)
continue;
found_fixed = 1;
} else if (found_fixed) { /* don't use a non-fixed heap */
return NULL;
}
#endif
for (ls1=h->free_list, ls2=ls1->next; ls2; ls1=ls2, ls2=ls2->next) {
if (ls2->size >= size) {
@ -617,9 +631,30 @@ void* sexp_try_alloc (sexp ctx, size_t size) {
return NULL;
}
#if SEXP_USE_FIXED_CHUNK_SIZE_HEAPS
int sexp_find_fixed_chunk_heap_usage(sexp ctx, size_t size, size_t* sum_freed, size_t* total_size) {
sexp_heap h;
sexp_free_list ls;
size_t avail=0, total=0;
for (h=sexp_context_heap(ctx); h; h=h->next) {
if (h->chunk_size == size || !h->chunk_size) {
for (; h && (h->chunk_size == size || !h->chunk_size); h=h->next) {
total += h->size;
for (ls=h->free_list; ls; ls=ls->next)
avail += ls->size;
}
*sum_freed = avail;
*total_size = total;
return h && h->chunk_size > 0;
}
}
return 0;
}
#endif
void* sexp_alloc (sexp ctx, size_t size) {
void *res;
size_t max_freed, sum_freed, total_size;
size_t max_freed, sum_freed, total_size=0;
sexp_heap h = sexp_context_heap(ctx);
#if SEXP_USE_TRACK_ALLOC_SIZES
size_t size_bucket;
@ -637,7 +672,11 @@ void* sexp_alloc (sexp ctx, size_t size) {
res = sexp_try_alloc(ctx, size);
if (! res) {
max_freed = sexp_unbox_fixnum(sexp_gc(ctx, &sum_freed));
#if SEXP_USE_FIXED_CHUNK_SIZE_HEAPS
sexp_find_fixed_chunk_heap_usage(ctx, size, &sum_freed, &total_size);
#else
total_size = sexp_heap_total_size(sexp_context_heap(ctx));
#endif
if (((max_freed < size)
|| ((total_size > sum_freed)
&& (total_size - sum_freed) > (total_size*SEXP_GROW_HEAP_RATIO)))

View file

@ -273,6 +273,11 @@
#define SEXP_GROW_HEAP_RATIO 0.75
#endif
/* how much to expand the heap size by */
#ifndef SEXP_GROW_HEAP_FACTOR
#define SEXP_GROW_HEAP_FACTOR 2 /* 1.6180339887498948482 */
#endif
/* the default number of opcodes to run each thread for */
#ifndef SEXP_DEFAULT_QUANTUM
#define SEXP_DEFAULT_QUANTUM 500

View file

@ -546,8 +546,9 @@ struct sexp_struct {
#endif
char tailp, tracep, timeoutp, waitp, errorp;
sexp_uint_t last_fp;
sexp_uint_t gc_count;
#if SEXP_USE_TIME_GC
sexp_uint_t gc_count, gc_usecs;
sexp_uint_t gc_usecs;
#endif
#if SEXP_USE_TRACK_ALLOC_TIMES
sexp_uint_t alloc_count, alloc_usecs;
@ -1311,8 +1312,8 @@ enum sexp_uniform_vector_type {
#define sexp_context_dk(x) (sexp_field(x, context, SEXP_CONTEXT, dk))
#define sexp_context_params(x) (sexp_field(x, context, SEXP_CONTEXT, params))
#define sexp_context_last_fp(x) (sexp_field(x, context, SEXP_CONTEXT, last_fp))
#if SEXP_USE_TIME_GC
#define sexp_context_gc_count(x) (sexp_field(x, context, SEXP_CONTEXT, gc_count))
#if SEXP_USE_TIME_GC
#define sexp_context_gc_usecs(x) (sexp_field(x, context, SEXP_CONTEXT, gc_usecs))
#else
#define sexp_context_gc_count(x) 0

4
sexp.c
View file

@ -606,7 +606,9 @@ sexp sexp_bootstrap_context (sexp_uint_t size, sexp_uint_t max_size) {
sexp_heap heap;
struct sexp_struct dummy_ctx;
if (size < SEXP_MINIMUM_HEAP_SIZE) size = SEXP_INITIAL_HEAP_SIZE;
heap = sexp_make_heap(sexp_heap_align(size), sexp_heap_align(max_size), 0);
size = sexp_heap_align(size);
max_size = sexp_heap_align(max_size);
heap = sexp_make_heap(size, max_size, 0);
if (!heap) return 0;
sexp_pointer_tag(&dummy_ctx) = SEXP_CONTEXT;
sexp_context_saves(&dummy_ctx) = NULL;