unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
From: Andy Wingo <wingo@pobox.com>
To: ludo@gnu.org (Ludovic Courtès)
Cc: guile-devel@gnu.org, Neil Jerram <neil@ossau.uklinux.net>
Subject: Re: [PATCH] Configure GMP to use GC allocation functions, remove bignum finalizers
Date: Tue, 29 Nov 2011 00:50:07 +0100	[thread overview]
Message-ID: <87liqzajtc.fsf@pobox.com> (raw)
In-Reply-To: <87zkff6dyr.fsf@gnu.org> ("Ludovic Courtès"'s message of "Tue, 29 Nov 2011 00:10:04 +0100")

[-- Attachment #1: Type: text/plain, Size: 625 bytes --]

On Tue 29 Nov 2011 00:10, ludo@gnu.org (Ludovic Courtès) writes:

> Andy Wingo <wingo@pobox.com> skribis:
>
>> On Sun 27 Nov 2011 22:25, ludo@gnu.org (Ludovic Courtès) writes:
>>
>>> The problem is that this measurement doesn’t allow us to differentiate
>>> between a growing heap with objects that may be freed as a result of
>>> running the GC, and a growing heap just because the application needs
>>> more malloc’d objects.
>>
>> This is true, but typically the heap stabilizes at some point.
>
> Ooh, re-reading your previous message, I now see what you mean, and it
> makes sense to me.

WDYT?


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-increase-garbage-collection-rate-if-the-process-is-g.patch --]
[-- Type: text/x-diff, Size: 6389 bytes --]

From 5dc96678aba01297a127aa6f3781ecedec3b24f1 Mon Sep 17 00:00:00 2001
From: Andy Wingo <wingo@pobox.com>
Date: Tue, 29 Nov 2011 00:48:56 +0100
Subject: [PATCH] increase garbage collection rate if the process is growing

* configure.ac: Check for GC_get_free_space_divisor.
* libguile/gc.c (GC_get_free_space_divisor): Define an implementation,
  if needed.
  (accumulate_gc_timer): Fix indentation.
  (get_image_size): New terrible hack.  Needs implementations on other
  platforms.
  (adjust_gc_frequency): Attempt to adjust the GC frequency based on
  process image growth.  Needs more comments.
  (scm_init_gc): Add the adjust_gc_frequency to the after_gc_c_hook.
---
 configure.ac  |    2 +-
 libguile/gc.c |  108 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 107 insertions(+), 3 deletions(-)

diff --git a/configure.ac b/configure.ac
index 3a56cda..d63dd63 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1259,7 +1259,7 @@ save_LIBS="$LIBS"
 LIBS="$BDW_GC_LIBS $LIBS"
 CFLAGS="$BDW_GC_CFLAGS $CFLAGS"
 
-AC_CHECK_FUNCS([GC_do_blocking GC_call_with_gc_active GC_pthread_exit GC_pthread_cancel GC_allow_register_threads GC_pthread_sigmask GC_set_start_callback GC_get_heap_usage_safe])
+AC_CHECK_FUNCS([GC_do_blocking GC_call_with_gc_active GC_pthread_exit GC_pthread_cancel GC_allow_register_threads GC_pthread_sigmask GC_set_start_callback GC_get_heap_usage_safe GC_get_free_space_divisor])
 
 # Though the `GC_do_blocking ()' symbol is present in GC 7.1, it is not
 # declared, and has a different type (returning void instead of
diff --git a/libguile/gc.c b/libguile/gc.c
index 4895b7d..281efde 100644
--- a/libguile/gc.c
+++ b/libguile/gc.c
@@ -27,6 +27,7 @@
 #include <stdio.h>
 #include <errno.h>
 #include <string.h>
+#include <math.h>
 
 #ifdef __ia64__
 #include <ucontext.h>
@@ -194,6 +195,8 @@ SCM_DEFINE (scm_set_debug_cell_accesses_x, "set-debug-cell-accesses!", 1, 0, 0,
 
 \f
 
+/* Compatibility.  */
+
 #ifndef HAVE_GC_GET_HEAP_USAGE_SAFE
 static void
 GC_get_heap_usage_safe (GC_word *pheap_size, GC_word *pfree_bytes,
@@ -208,6 +211,14 @@ GC_get_heap_usage_safe (GC_word *pheap_size, GC_word *pfree_bytes,
 }
 #endif
 
+#ifndef HAVE_GC_GET_FREE_SPACE_DIVISOR
+static GC_word
+GC_get_free_space_divisor (void)
+{
+  return GC_free_space_divisor;
+}
+#endif
+
 \f
 /* Hooks.  */
 scm_t_c_hook scm_before_gc_c_hook;
@@ -230,6 +241,9 @@ unsigned long scm_gc_ports_collected = 0;
 static long gc_time_taken = 0;
 static long gc_start_time = 0;
 
+static unsigned long free_space_divisor;
+static unsigned long minimum_free_space_divisor;
+static double target_free_space_divisor;
 
 static unsigned long protected_obj_count = 0;
 
@@ -598,7 +612,10 @@ void
 scm_storage_prehistory ()
 {
   GC_all_interior_pointers = 0;
-  GC_set_free_space_divisor (scm_getenv_int ("GC_FREE_SPACE_DIVISOR", 3));
+  free_space_divisor = scm_getenv_int ("GC_FREE_SPACE_DIVISOR", 3);
+  minimum_free_space_divisor = free_space_divisor;
+  target_free_space_divisor = free_space_divisor;
+  GC_set_free_space_divisor (free_space_divisor);
 
   GC_INIT ();
 
@@ -742,7 +759,8 @@ accumulate_gc_timer (void * hook_data SCM_UNUSED,
                 void *data SCM_UNUSED)
 {
   if (gc_start_time)
-    { long now = scm_c_get_internal_run_time ();
+    {
+      long now = scm_c_get_internal_run_time ();
       gc_time_taken += now - gc_start_time;
       gc_start_time = 0;
     }
@@ -750,6 +768,91 @@ accumulate_gc_timer (void * hook_data SCM_UNUSED,
   return NULL;
 }
 
+static size_t
+get_image_size (void)
+{
+  unsigned long size, resident, share;
+  size_t ret;
+
+  FILE *fp = fopen ("/proc/self/statm", "r");
+
+  if (fp && fscanf (fp, "%lu %lu %lu", &size, &resident, &share) == 3)
+    ret = resident * 4096;
+
+  if (fp)
+    fclose (fp);
+
+  return ret;
+}
+
+static void *
+adjust_gc_frequency (void * hook_data SCM_UNUSED,
+                     void *fn_data SCM_UNUSED,
+                     void *data SCM_UNUSED)
+{
+  static size_t prev_image_size = 0;
+  static size_t prev_bytes_alloced = 0;
+  size_t image_size;
+  size_t bytes_alloced;
+  
+  image_size = get_image_size ();
+  bytes_alloced = GC_get_total_bytes ();
+
+#define HEURISTICS_DEBUG 0
+
+#if HEURISTICS_DEBUG
+  fprintf (stderr, "prev image / alloced: %lu / %lu\n", prev_image_size, prev_bytes_alloced);
+  fprintf (stderr, "     image / alloced: %lu / %lu\n", image_size, bytes_alloced);
+  fprintf (stderr, "divisor %lu / %f\n", free_space_divisor, target_free_space_divisor);
+#endif
+
+  if (prev_image_size && bytes_alloced != prev_bytes_alloced)
+    {
+      double growth_rate, new_target_free_space_divisor;
+      double damping_factor = 0.5;
+      double hysteresis = 0.1;
+
+      growth_rate = ((double) image_size - prev_image_size)
+        / ((double)bytes_alloced - prev_bytes_alloced);
+      
+#if HEURISTICS_DEBUG
+      fprintf (stderr, "growth rate %f\n", growth_rate);
+#endif
+
+      new_target_free_space_divisor = minimum_free_space_divisor;
+
+      if (growth_rate > 0)
+        new_target_free_space_divisor *= 1.0 + growth_rate;
+
+#if HEURISTICS_DEBUG
+      fprintf (stderr, "new divisor %f\n", new_target_free_space_divisor);
+#endif
+
+      target_free_space_divisor =
+        (damping_factor * target_free_space_divisor
+         + (1.0 - damping_factor) * new_target_free_space_divisor);
+
+#if HEURISTICS_DEBUG
+      fprintf (stderr, "new target divisor %f\n", target_free_space_divisor);
+#endif
+
+      if (free_space_divisor + 0.5 + hysteresis < target_free_space_divisor
+          || free_space_divisor - 0.5 - hysteresis > target_free_space_divisor)
+        {
+          free_space_divisor = lround (target_free_space_divisor);
+#if HEURISTICS_DEBUG
+          fprintf (stderr, "new divisor %lu\n", free_space_divisor);
+#endif
+          GC_set_free_space_divisor (free_space_divisor);
+        }
+    }
+
+  prev_image_size = image_size;
+  prev_bytes_alloced = bytes_alloced;
+
+  return NULL;
+}
+
 
 \f
 
@@ -847,6 +950,7 @@ scm_init_gc ()
   scm_c_hook_add (&scm_before_gc_c_hook, queue_after_gc_hook, NULL, 0);
   scm_c_hook_add (&scm_before_gc_c_hook, start_gc_timer, NULL, 0);
   scm_c_hook_add (&scm_after_gc_c_hook, accumulate_gc_timer, NULL, 0);
+  scm_c_hook_add (&scm_after_gc_c_hook, adjust_gc_frequency, NULL, 0);
 
 #ifdef HAVE_GC_SET_START_CALLBACK
   GC_set_start_callback (run_before_gc_c_hook);
-- 
1.7.7.3


[-- Attachment #3: Type: text/plain, Size: 26 bytes --]


-- 
http://wingolog.org/

  reply	other threads:[~2011-11-28 23:50 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-05-31 19:48 [PATCH] Configure GMP to use GC allocation functions, remove bignum finalizers Mark H Weaver
2011-05-31 20:07 ` Mark H Weaver
2011-05-31 21:52 ` Ludovic Courtès
2011-05-31 23:18   ` Neil Jerram
2011-05-31 23:32     ` Neil Jerram
2011-06-01  8:34     ` Andy Wingo
2011-06-02 23:14       ` Ludovic Courtès
2011-11-27 19:33       ` Andy Wingo
2011-11-27 21:25         ` Ludovic Courtès
2011-11-28 22:23           ` Andy Wingo
2011-11-28 23:10             ` Ludovic Courtès
2011-11-28 23:50               ` Andy Wingo [this message]
2011-11-29 11:06                 ` Ludovic Courtès
2011-11-29 11:35                   ` Andy Wingo
2011-11-29 13:20                     ` Ludovic Courtès
2011-11-29 12:45                   ` Andy Wingo
2011-11-29 13:18                     ` Ludovic Courtès
2011-11-29 14:44                       ` Andy Wingo
2011-11-29 16:22                         ` Ludovic Courtès
2011-12-02 11:10           ` Andy Wingo
2011-12-02 17:02             ` Ludovic Courtès
2011-12-02 18:12               ` Andy Wingo
2011-12-02 22:17                 ` Ludovic Courtès
2011-12-03 10:57                   ` Andy Wingo
2011-12-03 17:57                     ` Ludovic Courtès

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/guile/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87liqzajtc.fsf@pobox.com \
    --to=wingo@pobox.com \
    --cc=guile-devel@gnu.org \
    --cc=ludo@gnu.org \
    --cc=neil@ossau.uklinux.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).