Keep track of the amount of free space in the heap

This commit is contained in:
Justin Ethier 2015-12-09 22:46:00 -05:00
parent 26c586ed26
commit de0c19e1cd
2 changed files with 27 additions and 5 deletions

30
gc.c
View file

@ -86,6 +86,7 @@ gc_heap *gc_heap_create(size_t size, size_t max_size, size_t chunk_size)
h = malloc(gc_heap_pad_size(size)); h = malloc(gc_heap_pad_size(size));
if (!h) return NULL; if (!h) return NULL;
h->size = size; h->size = size;
h->free_size = size;
h->chunk_size = chunk_size; h->chunk_size = chunk_size;
h->max_size = max_size; h->max_size = max_size;
h->data = (char *) gc_heap_align(sizeof(h->data) + (uint)&(h->data)); h->data = (char *) gc_heap_align(sizeof(h->data) + (uint)&(h->data));
@ -300,6 +301,7 @@ void *gc_try_alloc(gc_heap *h, size_t size, char *obj, gc_thread_data *thd)
} }
// Copy object into heap now to avoid any uninitialized memory issues // Copy object into heap now to avoid any uninitialized memory issues
gc_copy_obj(f2, obj, thd); gc_copy_obj(f2, obj, thd);
h->free_size -= gc_allocated_bytes(obj, NULL, NULL);
pthread_mutex_unlock(&heap_lock); pthread_mutex_unlock(&heap_lock);
return f2; return f2;
} }
@ -411,9 +413,21 @@ size_t gc_heap_total_size(gc_heap *h)
return total_size; return total_size;
} }
size_t gc_heap_total_free(gc_heap *h)
{
size_t total_size = 0;
pthread_mutex_lock(&heap_lock);
while(h) {
total_size += h->free_size;
h = h->next;
}
pthread_mutex_unlock(&heap_lock);
return total_size;
}
size_t gc_sweep(gc_heap *h, size_t *sum_freed_ptr) size_t gc_sweep(gc_heap *h, size_t *sum_freed_ptr)
{ {
size_t freed, max_freed=0, sum_freed=0, size; size_t freed, max_freed=0, heap_freed = 0, sum_freed=0, size;
object p, end; object p, end;
gc_free_list *q, *r, *s; gc_free_list *q, *r, *s;
@ -467,7 +481,7 @@ size_t gc_sweep(gc_heap *h, size_t *sum_freed_ptr)
#endif #endif
mark(p) = gc_color_blue; // Needed? mark(p) = gc_color_blue; // Needed?
// free p // free p
sum_freed += size; heap_freed += size;
if (((((char *)q) + q->size) == (char *)p) && (q != h->free_list)) { if (((((char *)q) + q->size) == (char *)p) && (q != h->free_list)) {
/* merge q with p */ /* merge q with p */
if (r && r->size && ((((char *)p)+size) == (char *)r)) { if (r && r->size && ((((char *)p)+size) == (char *)r)) {
@ -505,6 +519,9 @@ size_t gc_sweep(gc_heap *h, size_t *sum_freed_ptr)
p = (object)(((char *)p) + size); p = (object)(((char *)p) + size);
} }
} }
h->free_size += heap_freed;
sum_freed += heap_freed;
heap_freed = 0;
} }
pthread_mutex_unlock(&heap_lock); pthread_mutex_unlock(&heap_lock);
if (sum_freed_ptr) *sum_freed_ptr = sum_freed; if (sum_freed_ptr) *sum_freed_ptr = sum_freed;
@ -1061,7 +1078,7 @@ void debug_dump_globals();
void gc_collector() void gc_collector()
{ {
int old_clear, old_mark; int old_clear, old_mark;
size_t freed = 0, max_freed = 0, total_size; size_t freed = 0, max_freed = 0, total_size, total_free;
#if GC_DEBUG_TRACE #if GC_DEBUG_TRACE
time_t sweep_start = time(NULL); time_t sweep_start = time(NULL);
#endif #endif
@ -1104,9 +1121,12 @@ fprintf(stderr, "DEBUG - after wait_handshake async\n");
// //
//sweep : //sweep :
max_freed = gc_sweep(gc_get_heap(), &freed); max_freed = gc_sweep(gc_get_heap(), &freed);
// TODO: grow heap if it is mostly full after collection?? total_size = gc_heap_total_size(gc_get_heap());
total_free = gc_heap_total_free(gc_get_heap());
#if GC_DEBUG_TRACE #if GC_DEBUG_TRACE
fprintf(stderr, "sweep done, freed = %d, max_freed = %d, elapsed = %ld\n", fprintf(stderr, "sweep done, total_size = %d, total_free = %d, freed = %d, max_freed = %d, elapsed = %ld\n",
total_size, total_free,
freed, max_freed, time(NULL) - sweep_start); freed, max_freed, time(NULL) - sweep_start);
#endif #endif
gc_stage = STAGE_RESTING; gc_stage = STAGE_RESTING;

View file

@ -89,6 +89,7 @@ struct gc_heap_t {
unsigned int size; unsigned int size;
unsigned int chunk_size; // 0 for any size, other and heap will only alloc chunks of that size unsigned int chunk_size; // 0 for any size, other and heap will only alloc chunks of that size
unsigned int max_size; unsigned int max_size;
unsigned int free_size;
gc_free_list *free_list; // TBD gc_free_list *free_list; // TBD
gc_heap *next; // TBD, linked list is not very efficient, but easy to work with as a start gc_heap *next; // TBD, linked list is not very efficient, but easy to work with as a start
char *data; char *data;
@ -150,6 +151,7 @@ void *gc_alloc(gc_heap *h, size_t size, char *obj, gc_thread_data *thd, int *hea
size_t gc_allocated_bytes(object obj, gc_free_list *q, gc_free_list *r); size_t gc_allocated_bytes(object obj, gc_free_list *q, gc_free_list *r);
gc_heap *gc_heap_last(gc_heap *h); gc_heap *gc_heap_last(gc_heap *h);
size_t gc_heap_total_size(gc_heap *h); size_t gc_heap_total_size(gc_heap *h);
size_t gc_heap_total_free(gc_heap *h);
//size_t gc_collect(gc_heap *h, size_t *sum_freed); //size_t gc_collect(gc_heap *h, size_t *sum_freed);
//void gc_mark(gc_heap *h, object obj); //void gc_mark(gc_heap *h, object obj);
void gc_mark_globals(void); void gc_mark_globals(void);