This is the mail archive of the guile@sourceware.cygnus.com mailing list for the Guile project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: tweaking gc behavior in guile-1.3.4


Russell McManus <russell.mcmanus@msdw.com> writes:

> I've got to find some way to decrease the frequency of GC in
> guile-1.3.4.  I've got a C++ program that uses guile extensively, and
> when the work load reaches a certain point, guile starts gc'ing almost
> continuously.  Maybe adding in the generational gc would help; is this
> easy/ somewhat reliable to do?

If you mean my gengc work, you've gotta find it first ;). Actually,
I'm really hoping to have something ready this week (it would've been
before new years, but I ended up with injured wrists and working on
test stuff, so I didn't have a chance to hit the gc the way I wanted;
I spent some time with it last night, and will again tonight, and
there's not much left to do before an alpha test version). The other
gc patch (sans generational stuff) should be fairly stable, but I
haven't had a chance to extract a few bug fixes and release them (and
some are a bit fatal, so it might not be a good idea to use it). As a
temporary, you can try the following patch (I actually worked this up
yesterday, but hadn't gotten around to putting it anywhere yet); this
lets you configure the sizes of heap segments, which may not totally
help, but then again, it might (if the total speed sink is because the
heap is getting too large and the program is swapping, for
example). Setting GUILEGC_SEG_SIZE to something large (like 262144 or
so) might help out with some of the problems. This one allows you to
set GUILEGC_INIT_SEG_SIZE, as well (it's usually a good idea to
keep that fairly small). It's against the current cvs, but should
probably apply to almost any version.

diff -c -c -r1.73 gc.c
*** gc.c	2000/01/05 19:25:36	1.73
--- gc.c	2000/01/12 20:58:16
***************
*** 93,100 ****
   * heap is needed.  SCM_HEAP_SEG_SIZE must fit into type scm_sizet.  This code
   * is in scm_init_storage() and alloc_some_heap() in sys.c
   * 
!  * If SCM_INIT_HEAP_SIZE can be allocated initially, the heap will grow by
!  * SCM_EXPHEAP(scm_heap_size) when more heap is needed.
   *
   * SCM_MIN_HEAP_SEG_SIZE is minimum size of heap to accept when more heap
   * is needed.
--- 93,101 ----
   * heap is needed.  SCM_HEAP_SEG_SIZE must fit into type scm_sizet.  This code
   * is in scm_init_storage() and alloc_some_heap() in sys.c
   * 
!  * If SCM_INIT_HEAP_SIZE can be allocated initially, the heap will
!  * grow by SCM_EXPHEAP(scm_heap_size) when more heap is needed if
!  * scm_expmem is enabled.
   *
   * SCM_MIN_HEAP_SEG_SIZE is minimum size of heap to accept when more heap
   * is needed.
***************
*** 106,129 ****
   * reclaimed by a GC triggered by must_malloc. If less than this is
   * reclaimed, the trigger threshold is raised. [I don't know what a
   * good value is. I arbitrarily chose 1/10 of the INIT_MALLOC_LIMIT to
!  * work around a oscillation that caused almost constant GC.]  
!  */
  
! #define SCM_INIT_HEAP_SIZE (32768L*sizeof(scm_cell))
! #define SCM_MIN_HEAP_SEG_SIZE (2048L*sizeof(scm_cell))
  #ifdef _QC
  # define SCM_HEAP_SEG_SIZE 32768L
  #else
  # ifdef sequent
! #  define SCM_HEAP_SEG_SIZE (7000L*sizeof(scm_cell))
  # else
! #  define SCM_HEAP_SEG_SIZE (16384L*sizeof(scm_cell))
  # endif
  #endif
  #define SCM_EXPHEAP(scm_heap_size) (scm_heap_size*2)
  #define SCM_INIT_MALLOC_LIMIT 100000
  #define SCM_MTRIGGER_HYSTERESIS (SCM_INIT_MALLOC_LIMIT/10)
  
  /* CELL_UP and CELL_DN are used by scm_init_heap_seg to find scm_cell aligned inner
     bounds for allocated storage */
  
--- 107,142 ----
   * reclaimed by a GC triggered by must_malloc. If less than this is
   * reclaimed, the trigger threshold is raised. [I don't know what a
   * good value is. I arbitrarily chose 1/10 of the INIT_MALLOC_LIMIT to
!  * work around a oscillation that caused almost constant GC.]  */
! 
! /* The change here is that these are the number of cells for each
!    segments, and not the actual size; the variables below are set to
!    the actual mallocated size */
  
! #define SCM_INIT_HEAP_SIZE (16384L)
! #define SCM_MIN_HEAP_SEG_SIZE (2048L)
  #ifdef _QC
  # define SCM_HEAP_SEG_SIZE 32768L
  #else
  # ifdef sequent
! #  define SCM_HEAP_SEG_SIZE 7000L
  # else
! #  define SCM_HEAP_SEG_SIZE 65536L
  # endif
  #endif
  #define SCM_EXPHEAP(scm_heap_size) (scm_heap_size*2)
  #define SCM_INIT_MALLOC_LIMIT 100000
  #define SCM_MTRIGGER_HYSTERESIS (SCM_INIT_MALLOC_LIMIT/10)
  
+ #define SCM_CELLS_TO_BYTES(x) (x*sizeof(scm_cell))
+ 
+ static scm_sizet scm_heap_seg_size =
+        SCM_CELLS_TO_BYTES(SCM_HEAP_SEG_SIZE);
+ static scm_sizet scm_heap_init_seg_size =
+        SCM_CELLS_TO_BYTES(SCM_INIT_HEAP_SIZE);
+ static scm_sizet scm_heap_min_seg_size =
+        SCM_CELLS_TO_BYTES(SCM_MIN_HEAP_SEG_SIZE);
+ 
  /* CELL_UP and CELL_DN are used by scm_init_heap_seg to find scm_cell aligned inner
     bounds for allocated storage */
  
***************
*** 177,182 ****
--- 190,202 ----
   */
  SCM scm_weak_vectors;
  
+ /* scm_expmem is true if GUILEGC_ALLOW_EXPMEM is set in the executing
+  * environment to a non-zero value (or if you set it from c code). If
+  * scm_expmem is set, subsequent segment allocations will allocate
+  * segments of size SCM_EXPHEAP(scm_heap_size).  */
+ 
+ int scm_expmem = 0;
+ 
  /* GC Statistics Keeping
   */
  unsigned long scm_cells_allocated = 0;
***************
*** 219,226 ****
  
  static void scm_mark_weak_vector_spines(void);
  static scm_sizet init_heap_seg(SCM_CELLPTR, scm_sizet, int, SCM *);
! static void alloc_some_heap(int, SCM *);
  
  
  
  /* Debugging functions.  */
--- 239,272 ----
  
  static void scm_mark_weak_vector_spines(void);
  static scm_sizet init_heap_seg(SCM_CELLPTR, scm_sizet, int, SCM *);
! static void alloc_some_heap(int, scm_sizet, SCM *);
! 
! 
! /* setting gc parameters through the environment */
  
+ static void
+ scm_gc_get_env_settings(void);
+ 
+ static void
+ scm_gc_get_env_settings(void)
+ {
+   char *envptr;
+   if((envptr = getenv("GUILEGC_INIT_SEG_SIZE"))!=NULL) {
+     scm_heap_init_seg_size = 
+       SCM_CELLS_TO_BYTES(strtol(envptr, (char **)NULL, 10));
+   }
+   if((envptr = getenv("GUILEGC_SEG_SIZE")) != NULL) {
+     scm_heap_seg_size = 
+       SCM_CELLS_TO_BYTES(strtol(envptr, (char **)NULL, 10));
+   }
+   if((envptr = getenv("GUILEGC_MIN_SEG_SIZE")) != NULL) {
+     scm_heap_min_seg_size = 
+       SCM_CELLS_TO_BYTES(strtol(envptr, (char **)NULL, 10));
+   }
+   if((envptr = getenv("GUILEGC_ALLOW_EXPMEM")) != NULL) {
+     scm_expmem = strtol(envptr, (char **)NULL, 10);
+   }
+ }
  
  
  /* Debugging functions.  */
***************
*** 330,335 ****
--- 376,382 ----
        scm_freelist = SCM_CDR (scm_freelist);
        SCM_SETCAR (new, scm_tc16_allocated);
        ++scm_cells_allocated;
+       SCM_SETCAR(new, scm_tc16_allocated);
      }
  
    return new;
***************
*** 443,449 ****
    scm_igc ("cells");
    if ((scm_gc_cells_collected < MIN_GC_YIELD) || SCM_IMP (*freelistp))
      {
!       alloc_some_heap (ncells, freelistp);
      }
    SCM_REALLOW_INTS;
  }
--- 490,496 ----
    scm_igc ("cells");
    if ((scm_gc_cells_collected < MIN_GC_YIELD) || SCM_IMP (*freelistp))
      {
!       alloc_some_heap (ncells, scm_heap_seg_size, freelistp);
      }
    SCM_REALLOW_INTS;
  }
***************
*** 1575,1587 ****
   * phase of gc to identify probably gc roots (because they point
   * into valid segments at reasonable offsets).  */
  
- /* scm_expmem
-  * is true if the first segment was smaller than INIT_HEAP_SEG.
-  * If scm_expmem is set to one, subsequent segment allocations will
-  * allocate segments of size SCM_EXPHEAP(scm_heap_size).
-  */
- int scm_expmem = 0;
- 
  /* scm_heap_org
   * is the lowest base address of any heap segment.
   */
--- 1622,1627 ----
***************
*** 1689,1695 ****
  
  
  static void 
! alloc_some_heap (int ncells, SCM *freelistp)
  {
    struct scm_heap_seg_data * tmptable;
    SCM_CELLPTR ptr;
--- 1729,1735 ----
  
  
  static void 
! alloc_some_heap (int ncells, scm_sizet size, SCM *freelistp)
  {
    struct scm_heap_seg_data * tmptable;
    SCM_CELLPTR ptr;
***************
*** 1719,1732 ****
     * The rule for picking the size of a segment is explained in 
     * gc.h
     */
!   if (scm_expmem)
      {
        len = (scm_sizet) (SCM_EXPHEAP (scm_heap_size) * sizeof (scm_cell));
        if ((scm_sizet) (SCM_EXPHEAP (scm_heap_size) * sizeof (scm_cell)) != len)
  	len = 0;
      }
    else
!     len = SCM_HEAP_SEG_SIZE;
  
    {
      scm_sizet smallest;
--- 1759,1772 ----
     * The rule for picking the size of a segment is explained in 
     * gc.h
     */
!   if (scm_expmem && scm_heap_size) 
      {
        len = (scm_sizet) (SCM_EXPHEAP (scm_heap_size) * sizeof (scm_cell));
        if ((scm_sizet) (SCM_EXPHEAP (scm_heap_size) * sizeof (scm_cell)) != len)
  	len = 0;
      }
    else
!     len = size;
  
    {
      scm_sizet smallest;
***************
*** 1736,1742 ****
        len = (ncells * sizeof (scm_cell));
  
      /* Allocate with decaying ambition. */
!     while ((len >= SCM_MIN_HEAP_SEG_SIZE)
  	   && (len >= smallest))
        {
  	SCM_SYSCALL (ptr = (SCM_CELLPTR) malloc (len));
--- 1776,1782 ----
        len = (ncells * sizeof (scm_cell));
  
      /* Allocate with decaying ambition. */
!     while ((len >= scm_heap_min_seg_size)
  	   && (len >= smallest))
        {
  	SCM_SYSCALL (ptr = (SCM_CELLPTR) malloc (len));
***************
*** 1900,1921 ****
    scm_freelist = SCM_EOL;
    scm_expmem = 0;
  
-   j = SCM_HEAP_SEG_SIZE;
    scm_mtrigger = SCM_INIT_MALLOC_LIMIT;
    scm_heap_table = ((struct scm_heap_seg_data *)
  		    scm_must_malloc (sizeof (struct scm_heap_seg_data), "hplims"));
    if (0L == init_heap_size)
!     init_heap_size = SCM_INIT_HEAP_SIZE;
    j = init_heap_size;
!   if ((init_heap_size != j)
!       || !init_heap_seg ((SCM_CELLPTR) malloc (j), j, 1, &scm_freelist))
!     {
!       j = SCM_HEAP_SEG_SIZE;
!       if (!init_heap_seg ((SCM_CELLPTR) malloc (j), j, 1, &scm_freelist))
! 	return 1;
!     }
!   else
!     scm_expmem = 1;
    scm_heap_org = CELL_UP (scm_heap_table[0].bounds[0]);
    /* scm_hplims[0] can change. do not remove scm_heap_org */
    scm_weak_vectors = SCM_EOL;
--- 1940,1953 ----
    scm_freelist = SCM_EOL;
    scm_expmem = 0;
  
    scm_mtrigger = SCM_INIT_MALLOC_LIMIT;
    scm_heap_table = ((struct scm_heap_seg_data *)
  		    scm_must_malloc (sizeof (struct scm_heap_seg_data), "hplims"));
+   scm_gc_get_env_settings();
    if (0L == init_heap_size)
!     init_heap_size = scm_heap_init_seg_size;
    j = init_heap_size;
!   alloc_some_heap(1, j, &scm_freelist);
    scm_heap_org = CELL_UP (scm_heap_table[0].bounds[0]);
    /* scm_hplims[0] can change. do not remove scm_heap_org */
    scm_weak_vectors = SCM_EOL;

 

-- 
Gregh

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]