From c2cbcc57687ca716fb3e2166859b7be5880d80e2 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Sun, 4 Aug 2002 14:09:14 +0000 Subject: [PATCH] gc statistic tweaks --- ChangeLog | 4 ++++ NEWS | 23 +++++++++++++++++++++++ libguile/ChangeLog | 7 +++++-- libguile/dynl.c | 13 +++++++------ libguile/gc-malloc.c | 10 +++++----- libguile/gc-segment.c | 15 ++++++++++++--- libguile/gc.c | 35 +++++++++++++++++++++++------------ libguile/gc.h | 4 +++- libguile/private-gc.h | 1 + 9 files changed, 83 insertions(+), 29 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9f3b87388..fd4a89dc1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2002-08-04 Han-Wen + + * NEWS: add entries for GC and vector WB. + 2002-07-22 Han-Wen * autogen.sh (mscripts): find and check version number of diff --git a/NEWS b/NEWS index 1655989ff..611ca7239 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,29 @@ Changes since the stable branch: * Changes to the standalone interpreter +** SCM_VELTS macros is now read-only. For writing, use the new macros +SCM_WRITABLE_VELTS, SCM_SET_VECTOR_LENGTH. The use of +SCM_WRITABLE_VELTS is discouraged, though. + +** Garbage collector rewrite. + +The garbage collector is cleaned up a lot, and now uses lazy +sweeping. This is reflected in the output of (gc-stats); since cells +are being freed when they are allocated, the cells-allocated field +stays roughly constant. + +For malloc related triggers, the behavior is changed. It uses the same +heuristic as the cell-triggered collections. It may be tuned with the +environment variables GUILE_MIN_YIELD_MALLOC. This is the percentage +for minimum yield of malloc related triggers; (default: 40) +GUILE_INIT_MALLOC_LIMIT is the trigger for doing a GC. The default is +200 kb. + +Debugging operations for the freelist have been deprecated, along with +the C variables that control garbage collection. The environment +variables GUILE_MAX_SEGMENT_SIZE, GUILE_INIT_SEGMENT_SIZE_2, +GUILE_INIT_SEGMENT_SIZE_1, and GUILE_MIN_YIELD_2 should be used. + ** New command line option `--no-debug'. Specifying `--no-debug' on the command line will keep the debugging diff --git a/libguile/ChangeLog b/libguile/ChangeLog index 7ec6feb57..8bbe74abb 100644 --- a/libguile/ChangeLog +++ b/libguile/ChangeLog @@ -1,9 +1,12 @@ 2002-08-04 Han-Wen + * gc.c (s_scm_gc_stats): add cell-yield and malloc-yield statistic + to gc-stats. + * numbers.c (big2str): return "0" for 0 iso. "" - * gc-segment.c, gc-malloc.c gc-mark.c, gc-freelist.c, gc-card.c, private-gc.h: - new file + * gc-segment.c, gc-malloc.c gc-mark.c, gc-freelist.c, gc-card.c, + private-gc.h: new file * gc.c: completely revised and cleaned up the GC. It now uses lazy sweeping. More documentation in workbook/newgc.text diff --git a/libguile/dynl.c b/libguile/dynl.c index 4cc46d1e3..cb1e71fbd 100644 --- a/libguile/dynl.c +++ b/libguile/dynl.c @@ -77,13 +77,14 @@ maybe_drag_in_eprintf () #include "libltdl/ltdl.h" -/* From the libtool manual: "Note that libltdl is not threadsafe, - i.e. a multithreaded application has to use a mutex for libltdl.". +/* + From the libtool manual: "Note that libltdl is not threadsafe, + i.e. a multithreaded application has to use a mutex for libltdl.". - Guile does not currently support pre-emptive threads, so there is - no mutex. Previously SCM_DEFER_INTS and SCM_ALLOW_INTS were used: - they are mentioned here in case somebody is grepping for thread - problems ;) + Guile does not currently support pre-emptive threads, so there is + no mutex. Previously SCM_DEFER_INTS and SCM_ALLOW_INTS were used: + they are mentioned here in case somebody is grepping for thread + problems ;) */ static void * diff --git a/libguile/gc-malloc.c b/libguile/gc-malloc.c index 40d4ef907..a1d8f2dc8 100644 --- a/libguile/gc-malloc.c +++ b/libguile/gc-malloc.c @@ -92,7 +92,7 @@ extern unsigned long * __libc_ia64_register_backing_store_base; alloced memory, which won't go away on GC. Let's set the init such that we get a nice yield on the next allocation: */ -#define SCM_DEFAULT_INIT_MALLOC_LIMIT 200000 +#define SCM_DEFAULT_INIT_MALLOC_LIMIT 200*1024 #define SCM_DEFAULT_MALLOC_MINYIELD 40 @@ -203,8 +203,8 @@ scm_gc_register_collectable_memory (void *mem, size_t size, const char *what) scm_igc (what); scm_i_sweep_all_segments("mtrigger"); - yield = (prev_alloced - scm_mallocated) / (float) prev_alloced; - + yield = (prev_alloced - scm_mallocated) / (float) prev_alloced; + scm_gc_malloc_yield_percentage = (int) (100 * yield); /* fprintf (stderr, "prev %lud , now %lud, yield %4.2lf, want %d", prev_alloced, scm_mallocated, 100.0*yield, scm_i_minyield_malloc); @@ -225,9 +225,9 @@ scm_gc_register_collectable_memory (void *mem, size_t size, const char *what) /* fprintf (stderr, "Mtrigger sweep: ineffective. New trigger %d\n", scm_mtrigger); */ - - } + + } #ifdef GUILE_DEBUG_MALLOC diff --git a/libguile/gc-segment.c b/libguile/gc-segment.c index a3859df7b..d3a48f2ab 100644 --- a/libguile/gc-segment.c +++ b/libguile/gc-segment.c @@ -195,7 +195,12 @@ scm_i_sweep_some_cards (scm_t_heap_segment *seg) scm_gc_cells_swept += cards_swept * (SCM_GC_CARD_N_CELLS - SCM_GC_CARD_N_HEADER_CELLS); scm_gc_cells_collected += collected * seg->span; + + if (!seg->first_time) + scm_cells_allocated -= collected * seg->span; + seg->freelist->collected += collected * seg->span; + if(next_free == seg->bounds[1]) { @@ -212,8 +217,10 @@ scm_i_sweep_some_cards (scm_t_heap_segment *seg) statistics, it just frees the memory pointed to by to-be-swept cells. - Implementation is slightly ugh, and how do we handle the swept_cells - statistic? + Implementation is slightly ugh. + + FIXME: if you do scm_i_sweep_segment(), and then allocate from this + segment again, the statistics are off. */ void scm_i_sweep_segment (scm_t_heap_segment * seg) @@ -221,11 +228,13 @@ scm_i_sweep_segment (scm_t_heap_segment * seg) scm_t_cell * p = seg->next_free_card; int yield = scm_gc_cells_collected; int coll = seg->freelist->collected; - + int alloc = scm_cells_allocated ; + while (scm_i_sweep_some_cards (seg) != SCM_EOL) ; scm_gc_cells_collected = yield; + scm_cells_allocated = alloc; seg->freelist->collected = coll; seg->next_free_card =p; diff --git a/libguile/gc.c b/libguile/gc.c index 0a4a1cfad..58ede2266 100644 --- a/libguile/gc.c +++ b/libguile/gc.c @@ -256,7 +256,7 @@ SCM scm_structs_to_free; /* GC Statistics Keeping */ -unsigned long scm_cells_allocated = 0; +long scm_cells_allocated = 0; unsigned long scm_mallocated = 0; unsigned long scm_gc_cells_collected; unsigned long scm_gc_cells_collected_1 = 0; /* previous GC yield */ @@ -264,12 +264,14 @@ unsigned long scm_gc_malloc_collected; unsigned long scm_gc_ports_collected; unsigned long scm_gc_time_taken = 0; static unsigned long t_before_gc; -static unsigned long t_before_sweep; unsigned long scm_gc_mark_time_taken = 0; unsigned long scm_gc_times = 0; unsigned long scm_gc_cells_swept = 0; double scm_gc_cells_marked_acc = 0.; double scm_gc_cells_swept_acc = 0.; +int scm_gc_cell_yield_percentage =0; +int scm_gc_malloc_yield_percentage = 0; + SCM_SYMBOL (sym_cells_allocated, "cells-allocated"); SCM_SYMBOL (sym_heap_size, "cell-heap-size"); @@ -281,6 +283,8 @@ SCM_SYMBOL (sym_gc_mark_time_taken, "gc-mark-time-taken"); SCM_SYMBOL (sym_times, "gc-times"); SCM_SYMBOL (sym_cells_marked, "cells-marked"); SCM_SYMBOL (sym_cells_swept, "cells-swept"); +SCM_SYMBOL (sym_malloc_yield, "malloc-yield"); +SCM_SYMBOL (sym_cell_yield, "cell-yield"); @@ -292,7 +296,7 @@ unsigned scm_newcell2_count; /* {Scheme Interface to GC} */ - +extern int scm_gc_malloc_yield_percentage; SCM_DEFINE (scm_gc_stats, "gc-stats", 0, 0, 0, (), "Return an association list of statistics about Guile's current\n" @@ -304,7 +308,9 @@ SCM_DEFINE (scm_gc_stats, "gc-stats", 0, 0, 0, unsigned long int local_scm_mtrigger; unsigned long int local_scm_mallocated; unsigned long int local_scm_heap_size; - unsigned long int local_scm_cells_allocated; + int local_scm_gc_cell_yield_percentage; + int local_scm_gc_malloc_yield_percentage; + long int local_scm_cells_allocated; unsigned long int local_scm_gc_time_taken; unsigned long int local_scm_gc_times; unsigned long int local_scm_gc_mark_time_taken; @@ -341,14 +347,16 @@ SCM_DEFINE (scm_gc_stats, "gc-stats", 0, 0, 0, local_scm_gc_time_taken = scm_gc_time_taken; local_scm_gc_mark_time_taken = scm_gc_mark_time_taken; local_scm_gc_times = scm_gc_times; - - - local_scm_gc_cells_swept = scm_gc_cells_swept_acc + scm_gc_cells_swept; + local_scm_gc_malloc_yield_percentage = scm_gc_malloc_yield_percentage; + local_scm_gc_cell_yield_percentage= scm_gc_cell_yield_percentage; + + local_scm_gc_cells_swept = + (double) scm_gc_cells_swept_acc + + (double) scm_gc_cells_swept; local_scm_gc_cells_marked = scm_gc_cells_marked_acc +(double) scm_gc_cells_swept -(double) scm_gc_cells_collected; - for (i = table_size; i--;) { heap_segs = scm_cons (scm_cons (scm_ulong2num (bounds[2*i]), @@ -357,7 +365,7 @@ SCM_DEFINE (scm_gc_stats, "gc-stats", 0, 0, 0, } answer = scm_list_n (scm_cons (sym_gc_time_taken, scm_ulong2num (local_scm_gc_time_taken)), - scm_cons (sym_cells_allocated, scm_ulong2num (local_scm_cells_allocated)), + scm_cons (sym_cells_allocated, scm_long2num (local_scm_cells_allocated)), scm_cons (sym_heap_size, scm_ulong2num (local_scm_heap_size)), scm_cons (sym_mallocated, scm_ulong2num (local_scm_mallocated)), scm_cons (sym_mtrigger, scm_ulong2num (local_scm_mtrigger)), @@ -365,6 +373,8 @@ SCM_DEFINE (scm_gc_stats, "gc-stats", 0, 0, 0, scm_cons (sym_gc_mark_time_taken, scm_ulong2num (local_scm_gc_mark_time_taken)), scm_cons (sym_cells_marked, scm_i_dbl2big (local_scm_gc_cells_marked)), scm_cons (sym_cells_swept, scm_i_dbl2big (local_scm_gc_cells_swept)), + scm_cons (sym_malloc_yield, scm_long2num (local_scm_gc_malloc_yield_percentage)), + scm_cons (sym_cell_yield, scm_long2num (local_scm_gc_cell_yield_percentage)), scm_cons (sym_heap_segments, heap_segs), SCM_UNDEFINED); SCM_ALLOW_INTS; @@ -381,8 +391,10 @@ gc_start_stats (const char *what SCM_UNUSED) scm_gc_cells_marked_acc += (double) scm_gc_cells_swept - (double) scm_gc_cells_collected; - scm_gc_cells_swept_acc += scm_gc_cells_swept; + scm_gc_cells_swept_acc += (double) scm_gc_cells_swept; + scm_gc_cell_yield_percentage = ( scm_gc_cells_collected * 100 ) / SCM_HEAP_SIZE; + scm_gc_cells_swept = 0; scm_gc_cells_collected_1 = scm_gc_cells_collected; @@ -554,8 +566,7 @@ scm_igc (const char *what) scm_mark_all (); - t_before_sweep = scm_c_get_internal_run_time (); - scm_gc_mark_time_taken += (t_before_sweep - t_before_gc); + scm_gc_mark_time_taken += (scm_c_get_internal_run_time () - t_before_gc); scm_c_hook_run (&scm_before_sweep_c_hook, 0); diff --git a/libguile/gc.h b/libguile/gc.h index bd86ad1f0..1e688d65a 100644 --- a/libguile/gc.h +++ b/libguile/gc.h @@ -284,7 +284,9 @@ SCM_API unsigned long scm_gc_cells_collected; SCM_API unsigned long scm_gc_cells_collected; SCM_API unsigned long scm_gc_malloc_collected; SCM_API unsigned long scm_gc_ports_collected; -SCM_API unsigned long scm_cells_allocated; +SCM_API long scm_cells_allocated; +SCM_API int scm_gc_cell_yield_percentage; +SCM_API int scm_gc_malloc_yield_percentage; SCM_API unsigned long scm_mallocated; SCM_API unsigned long scm_mtrigger; diff --git a/libguile/private-gc.h b/libguile/private-gc.h index 52556bee6..3924e5044 100644 --- a/libguile/private-gc.h +++ b/libguile/private-gc.h @@ -109,6 +109,7 @@ typedef struct scm_t_cell_type_statistics { */ unsigned long heap_size; + } scm_t_cell_type_statistics; -- 2.20.1