1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-20 11:40:18 +02:00

attempt to handle steady-state mallocations better

* libguile/gc-malloc.c (scm_realloc): Call the new
  scm_gc_register_allocation() here.  If we have to collect, do a
  GC_gcollect_and_unmap.

* libguile/gc.c (scm_gc_register_allocation): Add a routine to track
  steady-state mallocation, and cause gc to run if there is a high
  mallocation rate.
  (adjust_gc_frequency): Reset the bytes-until-GC countdown timer.
This commit is contained in:
Andy Wingo 2011-11-29 21:36:31 +01:00
parent 9f7537dcab
commit fd51e66190
3 changed files with 40 additions and 1 deletions

View file

@ -89,12 +89,14 @@ scm_realloc (void *mem, size_t size)
{ {
void *ptr; void *ptr;
scm_gc_register_allocation (size);
SCM_SYSCALL (ptr = realloc (mem, size)); SCM_SYSCALL (ptr = realloc (mem, size));
if (ptr) if (ptr)
return ptr; return ptr;
/* Time is hard: trigger a full, ``stop-the-world'' GC, and try again. */ /* Time is hard: trigger a full, ``stop-the-world'' GC, and try again. */
GC_gcollect (); GC_gcollect_and_unmap ();
SCM_SYSCALL (ptr = realloc (mem, size)); SCM_SYSCALL (ptr = realloc (mem, size));
if (ptr) if (ptr)

View file

@ -787,6 +787,10 @@ get_image_size (void)
return ret; return ret;
} }
/* These are discussed later. */
static size_t bytes_until_gc;
static scm_i_pthread_mutex_t bytes_until_gc_lock = SCM_I_PTHREAD_MUTEX_INITIALIZER;
/* Make GC run more frequently when the process image size is growing, /* Make GC run more frequently when the process image size is growing,
measured against the number of bytes allocated through the GC. measured against the number of bytes allocated through the GC.
@ -832,6 +836,10 @@ adjust_gc_frequency (void * hook_data SCM_UNUSED,
size_t image_size; size_t image_size;
size_t bytes_alloced; size_t bytes_alloced;
scm_i_pthread_mutex_lock (&bytes_until_gc_lock);
bytes_until_gc = GC_get_heap_size ();
scm_i_pthread_mutex_unlock (&bytes_until_gc_lock);
image_size = get_image_size (); image_size = get_image_size ();
bytes_alloced = GC_get_total_bytes (); bytes_alloced = GC_get_total_bytes ();
@ -895,6 +903,33 @@ adjust_gc_frequency (void * hook_data SCM_UNUSED,
return NULL; return NULL;
} }
/* The adjust_gc_frequency routine handles transients in the process
image size. It can't handle instense non-GC-managed steady-state
allocation though, as it decays the FSD at steady-state down to its
minimum value.
The only real way to handle continuous, high non-GC allocation is to
let the GC know about it. This routine can handle non-GC allocation
rates that are similar in size to the GC-managed heap size.
*/
void
scm_gc_register_allocation (size_t size)
{
scm_i_pthread_mutex_lock (&bytes_until_gc_lock);
if (bytes_until_gc - size > bytes_until_gc)
{
bytes_until_gc = GC_get_heap_size ();
scm_i_pthread_mutex_unlock (&bytes_until_gc_lock);
GC_gcollect ();
}
else
{
bytes_until_gc -= size;
scm_i_pthread_mutex_unlock (&bytes_until_gc_lock);
}
}

View file

@ -182,6 +182,8 @@ SCM_INTERNAL void scm_i_gc (const char *what);
SCM_API void scm_gc_mark (SCM p); SCM_API void scm_gc_mark (SCM p);
SCM_API void scm_gc_sweep (void); SCM_API void scm_gc_sweep (void);
SCM_API void scm_gc_register_allocation (size_t size);
SCM_API void *scm_malloc (size_t size) SCM_MALLOC; SCM_API void *scm_malloc (size_t size) SCM_MALLOC;
SCM_API void *scm_calloc (size_t size) SCM_MALLOC; SCM_API void *scm_calloc (size_t size) SCM_MALLOC;
SCM_API void *scm_realloc (void *mem, size_t size); SCM_API void *scm_realloc (void *mem, size_t size);