summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Wingo <wingo@pobox.com>2011-11-29 21:36:31 +0100
committerAndy Wingo <wingo@pobox.com>2011-11-29 21:36:31 +0100
commitfd51e66190bde8cef74fec9725de4da3471901c4 (patch)
tree3fdacb8207c0579c81fcd9fc8117cce5ddcf95b3
parent9f7537dcabbded64afd631c0d57c84aced8173c5 (diff)
downloadguile-fd51e66190bde8cef74fec9725de4da3471901c4.tar.gz
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.
-rw-r--r--libguile/gc-malloc.c4
-rw-r--r--libguile/gc.c35
-rw-r--r--libguile/gc.h2
3 files changed, 40 insertions, 1 deletions
diff --git a/libguile/gc-malloc.c b/libguile/gc-malloc.c
index c64ea2f33..a7dab2a7e 100644
--- a/libguile/gc-malloc.c
+++ b/libguile/gc-malloc.c
@@ -89,12 +89,14 @@ scm_realloc (void *mem, size_t size)
{
void *ptr;
+ scm_gc_register_allocation (size);
+
SCM_SYSCALL (ptr = realloc (mem, size));
if (ptr)
return ptr;
/* 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));
if (ptr)
diff --git a/libguile/gc.c b/libguile/gc.c
index 6d420c8a6..c03c23982 100644
--- a/libguile/gc.c
+++ b/libguile/gc.c
@@ -787,6 +787,10 @@ get_image_size (void)
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,
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 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 ();
bytes_alloced = GC_get_total_bytes ();
@@ -895,6 +903,33 @@ adjust_gc_frequency (void * hook_data SCM_UNUSED,
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);
+ }
+}
+
diff --git a/libguile/gc.h b/libguile/gc.h
index a19b9de87..310569d29 100644
--- a/libguile/gc.h
+++ b/libguile/gc.h
@@ -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_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_calloc (size_t size) SCM_MALLOC;
SCM_API void *scm_realloc (void *mem, size_t size);