1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-01 12:20:26 +02:00

Ludovic's patch for scm_t_sweep_statistics.

This commit is contained in:
Han-Wen Nienhuys 2006-02-14 11:38:30 +00:00
parent b712c10755
commit 4c7016dc06
6 changed files with 165 additions and 72 deletions

View file

@ -1,3 +1,36 @@
2006-01-04 Ludovic Court<E8>s <ludovic.courtes@laas.fr>
* gc-segment.c (scm_i_sweep_some_cards): Take a SWEEP_STATS
argument. Don't refer to SCM_GC_CELLS_COLLECTED and
SCM_CELLS_ALLOCATED. If SEG->FIRST_TIME, let CELLS_COLLECTED as zero.
Take into account SEG->SPAN when computing CELLS_SWEPT.
(scm_i_sweep_segment): Take one more argument, similarly.
(scm_i_sweep_all_segments): Likewise.
(scm_i_sweep_some_segments): Likewise.
(scm_i_adjust_min_yield): Change the way MIN_CELLS is computed: do not
refer to SCM_GC_CELLS_COLLECTED.
* gc-freelist.c (scm_i_adjust_min_yield): Take one more
argument, an `scm_i_sweep_statistics' object.
Change the way DELTA is collected: don't take into account
SCM_GC_CELLS_COLLECTED_1, only SWEEP_STATS.COLLECTED.
* gc-malloc.c (scm_realloc): Pass an extra argument
to `scm_i_sweep_all_segments ()'.
* gc.c (gc_start_stats): Updated accordingly.
(gc_end_stats): Take an additional SWEEP_STATS argument.
Decrement SCM_CELLS_ALLOCATED after calls to `scm_i_sweep_* ()'.
(scm_gc_for_newcell): Updated callers of `scm_i_sweep_*'.
Decrement SCM_CELLS_ALLOCATED.
(scm_i_gc): Likewise.
* private-gc.h (scm_i_sweep_*): Updated function
prototypes accordingly.
(scm_t_sweep_statistics): New type.
(scm_i_sweep_statistics_init): New macro.
(scm_i_sweep_statistics_sum): New macro
2006-02-12 Marius Vollmer <mvo@zagadka.de> 2006-02-12 Marius Vollmer <mvo@zagadka.de>
* unif.c (scm_dimensions_to_uniform_array): Use the prototype for * unif.c (scm_dimensions_to_uniform_array): Use the prototype for

View file

@ -78,7 +78,8 @@ SCM_DEFINE (scm_gc_set_debug_check_freelist_x, "gc-set-debug-check-freelist!", 1
*/ */
void void
scm_i_adjust_min_yield (scm_t_cell_type_statistics *freelist) scm_i_adjust_min_yield (scm_t_cell_type_statistics *freelist,
scm_t_sweep_statistics sweep_stats)
{ {
/* min yield is adjusted upwards so that next predicted total yield /* min yield is adjusted upwards so that next predicted total yield
* (allocated cells actually freed by GC) becomes * (allocated cells actually freed by GC) becomes
@ -98,7 +99,7 @@ scm_i_adjust_min_yield (scm_t_cell_type_statistics *freelist)
{ {
/* Pick largest of last two yields. */ /* Pick largest of last two yields. */
long delta = ((SCM_HEAP_SIZE * freelist->min_yield_fraction / 100) long delta = ((SCM_HEAP_SIZE * freelist->min_yield_fraction / 100)
- (long) SCM_MAX (scm_gc_cells_collected_1, scm_gc_cells_collected)); - (long) sweep_stats.collected);
#ifdef DEBUGINFO #ifdef DEBUGINFO
fprintf (stderr, " after GC = %lu, delta = %ld\n", fprintf (stderr, " after GC = %lu, delta = %ld\n",
(unsigned long) scm_cells_allocated, (unsigned long) scm_cells_allocated,

View file

@ -105,6 +105,7 @@ void *
scm_realloc (void *mem, size_t size) scm_realloc (void *mem, size_t size)
{ {
void *ptr; void *ptr;
scm_t_sweep_statistics sweep_stats;
SCM_SYSCALL (ptr = realloc (mem, size)); SCM_SYSCALL (ptr = realloc (mem, size));
if (ptr) if (ptr)
@ -113,7 +114,7 @@ scm_realloc (void *mem, size_t size)
scm_i_scm_pthread_mutex_lock (&scm_i_sweep_mutex); scm_i_scm_pthread_mutex_lock (&scm_i_sweep_mutex);
scm_gc_running_p = 1; scm_gc_running_p = 1;
scm_i_sweep_all_segments ("realloc"); scm_i_sweep_all_segments ("realloc", &sweep_stats);
SCM_SYSCALL (ptr = realloc (mem, size)); SCM_SYSCALL (ptr = realloc (mem, size));
if (ptr) if (ptr)
@ -124,7 +125,7 @@ scm_realloc (void *mem, size_t size)
} }
scm_i_gc ("realloc"); scm_i_gc ("realloc");
scm_i_sweep_all_segments ("realloc"); scm_i_sweep_all_segments ("realloc", &sweep_stats);
scm_gc_running_p = 0; scm_gc_running_p = 0;
scm_i_pthread_mutex_unlock (&scm_i_sweep_mutex); scm_i_pthread_mutex_unlock (&scm_i_sweep_mutex);
@ -220,13 +221,14 @@ increase_mtrigger (size_t size, const char *what)
{ {
unsigned long prev_alloced; unsigned long prev_alloced;
float yield; float yield;
scm_t_sweep_statistics sweep_stats;
scm_i_scm_pthread_mutex_lock (&scm_i_sweep_mutex); scm_i_scm_pthread_mutex_lock (&scm_i_sweep_mutex);
scm_gc_running_p = 1; scm_gc_running_p = 1;
prev_alloced = mallocated; prev_alloced = mallocated;
scm_i_gc (what); scm_i_gc (what);
scm_i_sweep_all_segments ("mtrigger"); scm_i_sweep_all_segments ("mtrigger", &sweep_stats);
yield = (((float) prev_alloced - (float) scm_mallocated) yield = (((float) prev_alloced - (float) scm_mallocated)
/ (float) prev_alloced); / (float) prev_alloced);

View file

@ -140,15 +140,13 @@ scm_i_clear_segment_mark_space (scm_t_heap_segment *seg)
scm_i_segment_card_count (seg) * SCM_GC_CARD_BVEC_SIZE_IN_LONGS * SCM_SIZEOF_LONG); scm_i_segment_card_count (seg) * SCM_GC_CARD_BVEC_SIZE_IN_LONGS * SCM_SIZEOF_LONG);
} }
/* /* Sweep cards from SEG until we've gathered THRESHOLD cells. On return,
Sweep cards from SEG until we've gathered THRESHOLD cells *CELLS_SWEPT contains the number of cells that have been visited and
*CELLS_COLLECTED contains the number of cells actually collected. A
RETURN: freelist is returned, potentially empty. */
Freelist.
*/
SCM SCM
scm_i_sweep_some_cards (scm_t_heap_segment *seg) scm_i_sweep_some_cards (scm_t_heap_segment *seg,
scm_t_sweep_statistics *sweep_stats)
{ {
SCM cells = SCM_EOL; SCM cells = SCM_EOL;
int threshold = 512; int threshold = 512;
@ -166,14 +164,18 @@ scm_i_sweep_some_cards (scm_t_heap_segment *seg)
cards_swept ++; cards_swept ++;
} }
scm_gc_cells_swept += cards_swept * (SCM_GC_CARD_N_CELLS - SCM_GC_CARD_N_HEADER_CELLS); sweep_stats->swept = cards_swept * seg->span
scm_gc_cells_collected += collected * seg->span; * (SCM_GC_CARD_N_CELLS - SCM_GC_CARD_N_HEADER_CELLS);
if (!seg->first_time) if (!seg->first_time)
scm_cells_allocated -= collected * seg->span; {
/* scm_cells_allocated -= collected * seg->span; */
seg->freelist->collected += collected * seg->span; sweep_stats->collected = collected * seg->span;
}
else
sweep_stats->collected = 0;
seg->freelist->collected += collected * seg->span;
if(next_free == seg->bounds[1]) if(next_free == seg->bounds[1])
{ {
@ -196,31 +198,33 @@ scm_i_sweep_some_cards (scm_t_heap_segment *seg)
segment again, the statistics are off. segment again, the statistics are off.
*/ */
void void
scm_i_sweep_segment (scm_t_heap_segment * seg) scm_i_sweep_segment (scm_t_heap_segment *seg,
scm_t_sweep_statistics *sweep_stats)
{ {
scm_t_sweep_statistics sweep;
scm_t_cell * p = seg->next_free_card; scm_t_cell * p = seg->next_free_card;
int yield = scm_gc_cells_collected;
int coll = seg->freelist->collected;
unsigned long alloc = scm_cells_allocated ;
while (scm_i_sweep_some_cards (seg) != SCM_EOL) scm_i_sweep_statistics_init (sweep_stats);
;
scm_gc_cells_collected = yield; while (scm_i_sweep_some_cards (seg, &sweep) != SCM_EOL)
scm_cells_allocated = alloc; scm_i_sweep_statistics_sum (sweep_stats, sweep);
seg->freelist->collected = coll;
seg->next_free_card =p; seg->next_free_card =p;
} }
void void
scm_i_sweep_all_segments (char const *reason) scm_i_sweep_all_segments (char const *reason,
scm_t_sweep_statistics *sweep_stats)
{ {
int i= 0; unsigned i= 0;
scm_i_sweep_statistics_init (sweep_stats);
for (i = 0; i < scm_i_heap_segment_table_size; i++) for (i = 0; i < scm_i_heap_segment_table_size; i++)
{ {
scm_i_sweep_segment (scm_i_heap_segment_table[i]); scm_t_sweep_statistics sweep;
scm_i_sweep_segment (scm_i_heap_segment_table[i], &sweep);
scm_i_sweep_statistics_sum (sweep_stats, sweep);
} }
} }
@ -317,22 +321,28 @@ scm_i_insert_segment (scm_t_heap_segment * seg)
} }
SCM SCM
scm_i_sweep_some_segments (scm_t_cell_type_statistics * fl) scm_i_sweep_some_segments (scm_t_cell_type_statistics *fl,
scm_t_sweep_statistics *sweep_stats)
{ {
int i = fl->heap_segment_idx; int i = fl->heap_segment_idx;
SCM collected = SCM_EOL; SCM collected = SCM_EOL;
scm_i_sweep_statistics_init (sweep_stats);
if (i == -1) if (i == -1)
i++; i++;
for (; for (;
i < scm_i_heap_segment_table_size; i++) i < scm_i_heap_segment_table_size; i++)
{ {
scm_t_sweep_statistics sweep;
if (scm_i_heap_segment_table[i]->freelist != fl) if (scm_i_heap_segment_table[i]->freelist != fl)
continue; continue;
collected = scm_i_sweep_some_cards (scm_i_heap_segment_table[i]); collected = scm_i_sweep_some_cards (scm_i_heap_segment_table[i],
&sweep);
scm_i_sweep_statistics_sum (sweep_stats, sweep);
if (collected != SCM_EOL) /* Don't increment i */ if (collected != SCM_EOL) /* Don't increment i */
break; break;
@ -479,8 +489,7 @@ scm_i_get_new_heap_segment (scm_t_cell_type_statistics *freelist,
*/ */
float f = freelist->min_yield_fraction / 100.0; float f = freelist->min_yield_fraction / 100.0;
float h = SCM_HEAP_SIZE; float h = SCM_HEAP_SIZE;
float min_cells float min_cells = (f * h - scm_gc_cells_collected) / (1.0 - f);
= (f * h - scm_gc_cells_collected) / (1.0 - f);
/* Make heap grow with factor 1.5 */ /* Make heap grow with factor 1.5 */
len = freelist->heap_size / 2; len = freelist->heap_size / 2;

View file

@ -403,30 +403,31 @@ gc_start_stats (const char *what SCM_UNUSED)
{ {
t_before_gc = scm_c_get_internal_run_time (); t_before_gc = scm_c_get_internal_run_time ();
scm_gc_cells_marked_acc += (double) scm_gc_cells_swept scm_gc_malloc_collected = 0;
- (double) scm_gc_cells_collected; scm_gc_ports_collected = 0;
scm_gc_cells_swept_acc += (double) scm_gc_cells_swept; }
scm_gc_cell_yield_percentage = ( scm_gc_cells_collected * 100 ) / SCM_HEAP_SIZE; static void
gc_end_stats (scm_t_sweep_statistics sweep_stats)
scm_gc_cells_swept = 0; {
scm_gc_cells_collected_1 = scm_gc_cells_collected; unsigned long t = scm_c_get_internal_run_time ();
scm_gc_time_taken += (t - t_before_gc);
/* /*
CELLS SWEPT is another word for the number of cells that were CELLS SWEPT is another word for the number of cells that were
examined during GC. YIELD is the number that we cleaned examined during GC. YIELD is the number that we cleaned
out. MARKED is the number that weren't cleaned. out. MARKED is the number that weren't cleaned.
*/ */
scm_gc_cells_collected = 0; scm_gc_cells_marked_acc += (double) sweep_stats.swept
scm_gc_malloc_collected = 0; - (double) scm_gc_cells_collected;
scm_gc_ports_collected = 0; scm_gc_cells_swept_acc += (double) sweep_stats.swept;
}
static void scm_gc_cell_yield_percentage = (sweep_stats.collected * 100) / SCM_HEAP_SIZE;
gc_end_stats ()
{ scm_gc_cells_swept = sweep_stats.swept;
unsigned long t = scm_c_get_internal_run_time (); scm_gc_cells_collected_1 = scm_gc_cells_collected;
scm_gc_time_taken += (t - t_before_gc); scm_gc_cells_collected = sweep_stats.collected;
scm_cells_allocated -= sweep_stats.collected;
++scm_gc_times; ++scm_gc_times;
} }
@ -478,15 +479,19 @@ scm_gc_for_newcell (scm_t_cell_type_statistics *freelist, SCM *free_cells)
{ {
SCM cell; SCM cell;
int did_gc = 0; int did_gc = 0;
scm_t_sweep_statistics sweep_stats;
scm_i_scm_pthread_mutex_lock (&scm_i_sweep_mutex); scm_i_scm_pthread_mutex_lock (&scm_i_sweep_mutex);
scm_gc_running_p = 1; scm_gc_running_p = 1;
*free_cells = scm_i_sweep_some_segments (freelist); *free_cells = scm_i_sweep_some_segments (freelist, &sweep_stats);
scm_cells_allocated -= sweep_stats.collected;
if (*free_cells == SCM_EOL && scm_i_gc_grow_heap_p (freelist)) if (*free_cells == SCM_EOL && scm_i_gc_grow_heap_p (freelist))
{ {
freelist->heap_segment_idx = scm_i_get_new_heap_segment (freelist, abort_on_error); freelist->heap_segment_idx = scm_i_get_new_heap_segment (freelist, abort_on_error);
*free_cells = scm_i_sweep_some_segments (freelist); *free_cells = scm_i_sweep_some_segments (freelist, &sweep_stats);
scm_cells_allocated -= sweep_stats.collected;
} }
if (*free_cells == SCM_EOL) if (*free_cells == SCM_EOL)
@ -495,7 +500,7 @@ scm_gc_for_newcell (scm_t_cell_type_statistics *freelist, SCM *free_cells)
with the advent of lazy sweep, GC yield is only known just with the advent of lazy sweep, GC yield is only known just
before doing the GC. before doing the GC.
*/ */
scm_i_adjust_min_yield (freelist); scm_i_adjust_min_yield (freelist, sweep_stats);
/* /*
out of fresh cells. Try to get some new ones. out of fresh cells. Try to get some new ones.
@ -504,7 +509,8 @@ scm_gc_for_newcell (scm_t_cell_type_statistics *freelist, SCM *free_cells)
did_gc = 1; did_gc = 1;
scm_i_gc ("cells"); scm_i_gc ("cells");
*free_cells = scm_i_sweep_some_segments (freelist); *free_cells = scm_i_sweep_some_segments (freelist, &sweep_stats);
scm_cells_allocated -= sweep_stats.collected;
} }
if (*free_cells == SCM_EOL) if (*free_cells == SCM_EOL)
@ -513,7 +519,8 @@ scm_gc_for_newcell (scm_t_cell_type_statistics *freelist, SCM *free_cells)
failed getting new cells. Get new juice or die. failed getting new cells. Get new juice or die.
*/ */
freelist->heap_segment_idx = scm_i_get_new_heap_segment (freelist, abort_on_error); freelist->heap_segment_idx = scm_i_get_new_heap_segment (freelist, abort_on_error);
*free_cells = scm_i_sweep_some_segments (freelist); *free_cells = scm_i_sweep_some_segments (freelist, &sweep_stats);
scm_cells_allocated -= sweep_stats.collected;
} }
if (*free_cells == SCM_EOL) if (*free_cells == SCM_EOL)
@ -545,6 +552,8 @@ scm_t_c_hook scm_after_gc_c_hook;
void void
scm_i_gc (const char *what) scm_i_gc (const char *what)
{ {
scm_t_sweep_statistics sweep_stats;
scm_i_thread_put_to_sleep (); scm_i_thread_put_to_sleep ();
scm_c_hook_run (&scm_before_gc_c_hook, 0); scm_c_hook_run (&scm_before_gc_c_hook, 0);
@ -571,7 +580,12 @@ scm_i_gc (const char *what)
Let's finish the sweep. The conservative GC might point into the Let's finish the sweep. The conservative GC might point into the
garbage, and marking that would create a mess. garbage, and marking that would create a mess.
*/ */
scm_i_sweep_all_segments("GC"); scm_i_sweep_all_segments ("GC", &sweep_stats);
/* Invariant: the number of cells collected (i.e., freed) must always be
lower than or equal to the number of cells "swept" (i.e., visited). */
assert (sweep_stats.collected <= sweep_stats.swept);
if (scm_mallocated < scm_i_deprecated_memory_return) if (scm_mallocated < scm_i_deprecated_memory_return)
{ {
/* The byte count of allocated objects has underflowed. This is /* The byte count of allocated objects has underflowed. This is
@ -624,7 +638,7 @@ scm_i_gc (const char *what)
scm_gc_sweep (); scm_gc_sweep ();
scm_c_hook_run (&scm_after_sweep_c_hook, 0); scm_c_hook_run (&scm_after_sweep_c_hook, 0);
gc_end_stats (); gc_end_stats (sweep_stats);
scm_i_thread_wake_up (); scm_i_thread_wake_up ();
@ -635,6 +649,7 @@ scm_i_gc (const char *what)
*/ */
} }
/* {GC Protection Helper Functions} /* {GC Protection Helper Functions}
*/ */

View file

@ -118,11 +118,40 @@ typedef struct scm_t_cell_type_statistics {
} scm_t_cell_type_statistics; } scm_t_cell_type_statistics;
/* Sweep statistics. */
typedef struct scm_sweep_statistics
{
/* Number of cells "swept", i.e., visited during the sweep operation. */
unsigned swept;
/* Number of cells collected during the sweep operation. This number must
alsways be lower than or equal to SWEPT. */
unsigned collected;
} scm_t_sweep_statistics;
#define scm_i_sweep_statistics_init(_stats) \
do \
{ \
(_stats)->swept = (_stats)->collected = 0; \
} \
while (0)
#define scm_i_sweep_statistics_sum(_sum, _addition) \
do \
{ \
(_sum)->swept += (_addition).swept; \
(_sum)->collected += (_addition).collected; \
} \
while (0)
extern scm_t_cell_type_statistics scm_i_master_freelist; extern scm_t_cell_type_statistics scm_i_master_freelist;
extern scm_t_cell_type_statistics scm_i_master_freelist2; extern scm_t_cell_type_statistics scm_i_master_freelist2;
extern unsigned long scm_gc_cells_collected_1; extern unsigned long scm_gc_cells_collected_1;
void scm_i_adjust_min_yield (scm_t_cell_type_statistics *freelist); void scm_i_adjust_min_yield (scm_t_cell_type_statistics *freelist,
scm_t_sweep_statistics sweep_stats);
void scm_i_gc_sweep_freelist_reset (scm_t_cell_type_statistics *freelist); void scm_i_gc_sweep_freelist_reset (scm_t_cell_type_statistics *freelist);
int scm_i_gc_grow_heap_p (scm_t_cell_type_statistics * freelist); int scm_i_gc_grow_heap_p (scm_t_cell_type_statistics * freelist);
@ -221,8 +250,10 @@ int scm_i_segment_cell_count (scm_t_heap_segment * seg);
void scm_i_clear_segment_mark_space (scm_t_heap_segment *seg); void scm_i_clear_segment_mark_space (scm_t_heap_segment *seg);
scm_t_heap_segment * scm_i_make_empty_heap_segment (scm_t_cell_type_statistics*); scm_t_heap_segment * scm_i_make_empty_heap_segment (scm_t_cell_type_statistics*);
SCM scm_i_sweep_some_cards (scm_t_heap_segment *seg); SCM scm_i_sweep_some_cards (scm_t_heap_segment *seg,
void scm_i_sweep_segment (scm_t_heap_segment * seg); scm_t_sweep_statistics *sweep_stats);
void scm_i_sweep_segment (scm_t_heap_segment *seg,
scm_t_sweep_statistics *sweep_stats);
void scm_i_heap_segment_statistics (scm_t_heap_segment *seg, SCM tab); void scm_i_heap_segment_statistics (scm_t_heap_segment *seg, SCM tab);
@ -232,9 +263,11 @@ long int scm_i_find_heap_segment_containing_object (SCM obj);
int scm_i_get_new_heap_segment (scm_t_cell_type_statistics *, policy_on_error); int scm_i_get_new_heap_segment (scm_t_cell_type_statistics *, policy_on_error);
void scm_i_clear_mark_space (void); void scm_i_clear_mark_space (void);
void scm_i_sweep_segments (void); void scm_i_sweep_segments (void);
SCM scm_i_sweep_some_segments (scm_t_cell_type_statistics * fl); SCM scm_i_sweep_some_segments (scm_t_cell_type_statistics *fl,
scm_t_sweep_statistics *sweep_stats);
void scm_i_reset_segments (void); void scm_i_reset_segments (void);
void scm_i_sweep_all_segments (char const *reason); void scm_i_sweep_all_segments (char const *reason,
scm_t_sweep_statistics *sweep_stats);
SCM scm_i_all_segments_statistics (SCM hashtab); SCM scm_i_all_segments_statistics (SCM hashtab);
void scm_i_make_initial_segment (int init_heap_size, scm_t_cell_type_statistics *freelist); void scm_i_make_initial_segment (int init_heap_size, scm_t_cell_type_statistics *freelist);