More improvements to 'time' word

db4
Slava Pestov 2008-05-07 23:09:18 -05:00
parent 1cbe87da82
commit 22a9a8b95e
4 changed files with 116 additions and 84 deletions

View File

@ -1,36 +1,54 @@
! Copyright (C) 2003, 2008 Slava Pestov. ! Copyright (C) 2003, 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: kernel math math.vectors memory io io.styles prettyprint USING: kernel math math.vectors memory io io.styles prettyprint
namespaces system sequences assocs ; namespaces system sequences splitting assocs strings ;
IN: tools.time IN: tools.time
: benchmark ( quot -- gctime runtime ) : benchmark ( quot -- gctime runtime )
millis >r call millis r> - ; inline millis >r call millis r> - ; inline
: stats. ( data -- ) : simple-table. ( values -- )
{
"Run time (ms):"
"Nursery GC time (ms):"
"Nursery GC #:"
"Aging GC time (ms):"
"Aging GC #:"
"Tenured GC time (ms):"
"Tenured GC #:"
"Cards scanned:"
"Decks scanned:"
"Code literal GC #:"
"Bytes copied:"
"Bytes collected:"
} swap zip
standard-table-style [ standard-table-style [
[ [
[ [
[ [ write ] with-cell ] [ pprint-cell ] bi* [
dup string?
[ [ write ] with-cell ]
[ pprint-cell ]
if
] each
] with-row ] with-row
] assoc-each ] each
] tabular-output ; ] tabular-output ;
: stats gc-stats millis prefix ; : time. ( data -- )
unclip
"==== RUNNING TIME" print nl pprint " ms" print nl
4 cut*
"==== GARBAGE COLLECTION" print nl
[
6 group
{
"GC count:"
"Cumulative GC time (ms):"
"Longest GC pause (ms):"
"Average GC pause (ms):"
"Objects copied:"
"Bytes copied:"
} prefix
flip
{ "" "Nursery" "Aging" "Tenured" } prefix
simple-table.
]
[
nl
{
"Total GC time (ms):"
"Cards scanned:"
"Decks scanned:"
"Code heap literal scans:"
} swap zip simple-table.
] bi* ;
: time ( quot -- ) : time ( quot -- )
stats >r call stats r> v- stats. ; inline gc-reset millis >r call gc-stats millis r> - prefix time. ; inline

View File

@ -144,6 +144,13 @@ void set_data_heap(F_DATA_HEAP *data_heap_)
clear_cards(NURSERY,TENURED); clear_cards(NURSERY,TENURED);
} }
void gc_reset(void)
{
int i;
for(i = 0; i < MAX_GEN_COUNT; i++)
memset(&gc_stats[i],0,sizeof(F_GC_STATS));
}
void init_data_heap(CELL gens, void init_data_heap(CELL gens,
CELL young_size, CELL young_size,
CELL aging_size, CELL aging_size,
@ -158,17 +165,13 @@ void init_data_heap(CELL gens,
extra_roots_region = alloc_segment(getpagesize()); extra_roots_region = alloc_segment(getpagesize());
extra_roots = extra_roots_region->start - CELLS; extra_roots = extra_roots_region->start - CELLS;
nursery_gc_time = 0; secure_gc = secure_gc_;
nursery_collections = 0;
aging_gc_time = 0; gc_reset();
aging_collections = 0;
tenured_gc_time = 0;
tenured_collections = 0;
cards_scanned = 0; cards_scanned = 0;
decks_scanned = 0; decks_scanned = 0;
code_heap_scans = 0; code_heap_scans = 0;
bytes_copied = 0;
secure_gc = secure_gc_;
} }
/* Size of the object pointed to by a tagged pointer */ /* Size of the object pointed to by a tagged pointer */
@ -312,21 +315,16 @@ void collect_card(F_CARD *ptr, CELL gen, CELL here)
F_CARD c = *ptr; F_CARD c = *ptr;
CELL offset = (c & CARD_BASE_MASK); CELL offset = (c & CARD_BASE_MASK);
if(offset == CARD_BASE_MASK) if(offset != CARD_BASE_MASK)
{ {
/* if(c == 0xff) CELL card_scan = (CELL)CARD_TO_ADDR(ptr) + offset;
critical_error("bad card",(CELL)ptr); CELL card_end = (CELL)CARD_TO_ADDR(ptr + 1);
else */
return; while(card_scan < card_end && card_scan < here)
card_scan = collect_next(card_scan);
cards_scanned++;
} }
CELL card_scan = (CELL)CARD_TO_ADDR(ptr) + offset;
CELL card_end = (CELL)CARD_TO_ADDR(ptr + 1);
while(card_scan < card_end && card_scan < here)
card_scan = collect_next(card_scan);
cards_scanned++;
} }
void collect_card_deck(F_DECK *deck, CELL gen, F_CARD mask, F_CARD unmask) void collect_card_deck(F_DECK *deck, CELL gen, F_CARD mask, F_CARD unmask)
@ -510,7 +508,11 @@ INLINE void *copy_untagged_object(void *pointer, CELL size)
longjmp(gc_jmp,1); longjmp(gc_jmp,1);
allot_barrier(newspace->here); allot_barrier(newspace->here);
newpointer = allot_zone(newspace,size); newpointer = allot_zone(newspace,size);
bytes_copied += size;
F_GC_STATS *s = &gc_stats[collecting_gen];
s->object_count++;
s->bytes_copied += size;
memcpy(newpointer,pointer,size); memcpy(newpointer,pointer,size);
return newpointer; return newpointer;
} }
@ -641,7 +643,7 @@ CELL collect_next(CELL scan)
INLINE void reset_generation(CELL i) INLINE void reset_generation(CELL i)
{ {
F_ZONE *z = (i == NURSERY ? &nursery : &data_heap->generations[i]); F_ZONE *z = (i == NURSERY ? &nursery : &data_heap->generations[i]);
bytes_collected += (z->here - z->start);
z->here = z->start; z->here = z->start;
if(secure_gc) if(secure_gc)
memset((void*)z->start,69,z->size); memset((void*)z->start,69,z->size);
@ -652,7 +654,9 @@ their allocation pointers and cards reset. */
void reset_generations(CELL from, CELL to) void reset_generations(CELL from, CELL to)
{ {
CELL i; CELL i;
for(i = from; i <= to; i++) reset_generation(i); for(i = from; i <= to; i++)
reset_generation(i);
clear_cards(from,to); clear_cards(from,to);
} }
@ -698,6 +702,13 @@ void begin_gc(CELL requested_bytes)
void end_gc(CELL gc_elapsed) void end_gc(CELL gc_elapsed)
{ {
F_GC_STATS *s = &gc_stats[collecting_gen];
s->collections++;
s->gc_time += gc_elapsed;
if(s->max_gc_time < gc_elapsed)
s->max_gc_time = gc_elapsed;
if(growing_data_heap) if(growing_data_heap)
{ {
dealloc_data_heap(old_data_heap); dealloc_data_heap(old_data_heap);
@ -712,28 +723,12 @@ void end_gc(CELL gc_elapsed)
old-school Cheney collector */ old-school Cheney collector */
if(collecting_gen != NURSERY) if(collecting_gen != NURSERY)
reset_generations(NURSERY,collecting_gen - 1); reset_generations(NURSERY,collecting_gen - 1);
if(collecting_gen == TENURED)
{
tenured_collections++;
tenured_gc_time += gc_elapsed;
GC_PRINT(END_AGING_GC,aging_collections,cards_scanned);
}
else if(HAVE_AGING_P && collecting_gen == AGING)
{
aging_collections++;
aging_gc_time += gc_elapsed;
GC_PRINT(END_NURSERY_GC,nursery_collections,cards_scanned);
}
} }
else else
{ {
/* all generations up to and including the one /* all generations up to and including the one
collected are now empty */ collected are now empty */
reset_generations(NURSERY,collecting_gen); reset_generations(NURSERY,collecting_gen);
nursery_collections++;
nursery_gc_time += gc_elapsed;
} }
if(collecting_gen == TENURED) if(collecting_gen == TENURED)
@ -852,24 +847,38 @@ DEFINE_PRIMITIVE(gc)
gc(); gc();
} }
/* Push total time spent on GC */
DEFINE_PRIMITIVE(gc_stats) DEFINE_PRIMITIVE(gc_stats)
{ {
CELL array = tag_object(allot_array(ARRAY_TYPE,11,F)); GROWABLE_ARRAY(stats);
REGISTER_ROOT(array);
set_array_nth(untag_object(array),0,allot_cell(nursery_gc_time)); CELL i;
set_array_nth(untag_object(array),1,allot_cell(nursery_collections)); CELL total_gc_time = 0;
set_array_nth(untag_object(array),2,allot_cell(aging_gc_time));
set_array_nth(untag_object(array),3,allot_cell(aging_collections)); for(i = 0; i < MAX_GEN_COUNT; i++)
set_array_nth(untag_object(array),4,allot_cell(tenured_gc_time)); {
set_array_nth(untag_object(array),5,allot_cell(tenured_collections)); F_GC_STATS *s = &gc_stats[i];
set_array_nth(untag_object(array),6,tag_bignum(long_long_to_bignum(cards_scanned))); GROWABLE_ADD(stats,allot_cell(s->collections));
set_array_nth(untag_object(array),7,tag_bignum(long_long_to_bignum(decks_scanned))); GROWABLE_ADD(stats,allot_cell(s->gc_time));
set_array_nth(untag_object(array),8,allot_cell(code_heap_scans)); GROWABLE_ADD(stats,allot_cell(s->max_gc_time));
set_array_nth(untag_object(array),9,tag_bignum(long_long_to_bignum(bytes_copied))); GROWABLE_ADD(stats,allot_cell(s->collections == 0 ? 0 : s->gc_time / s->collections));
set_array_nth(untag_object(array),10,tag_bignum(long_long_to_bignum(bytes_collected))); GROWABLE_ADD(stats,allot_cell(s->object_count));
UNREGISTER_ROOT(array); GROWABLE_ADD(stats,tag_bignum(long_long_to_bignum(s->bytes_copied)));
dpush(array);
total_gc_time += s->gc_time;
}
GROWABLE_ADD(stats,allot_cell(total_gc_time));
GROWABLE_ADD(stats,tag_bignum(long_long_to_bignum(cards_scanned)));
GROWABLE_ADD(stats,tag_bignum(long_long_to_bignum(decks_scanned)));
GROWABLE_ADD(stats,allot_cell(code_heap_scans));
GROWABLE_TRIM(stats);
dpush(stats);
}
DEFINE_PRIMITIVE(gc_reset)
{
gc_reset();
} }
DEFINE_PRIMITIVE(become) DEFINE_PRIMITIVE(become)

View File

@ -138,6 +138,8 @@ void collect_cards(void);
/* the oldest generation */ /* the oldest generation */
#define TENURED (data_heap->gen_count-1) #define TENURED (data_heap->gen_count-1)
#define MAX_GEN_COUNT 3
/* used during garbage collection only */ /* used during garbage collection only */
F_ZONE *newspace; F_ZONE *newspace;
@ -158,16 +160,17 @@ void init_data_heap(CELL gens,
bool secure_gc_); bool secure_gc_);
/* statistics */ /* statistics */
CELL nursery_gc_time; typedef struct {
CELL nursery_collections; CELL collections;
CELL aging_gc_time; CELL gc_time;
CELL aging_collections; CELL max_gc_time;
CELL tenured_gc_time; CELL object_count;
CELL tenured_collections; u64 bytes_copied;
} F_GC_STATS;
F_GC_STATS gc_stats[MAX_GEN_COUNT];
u64 cards_scanned; u64 cards_scanned;
u64 decks_scanned; u64 decks_scanned;
u64 bytes_copied;
u64 bytes_collected;
CELL code_heap_scans; CELL code_heap_scans;
/* only meaningful during a GC */ /* only meaningful during a GC */
@ -388,6 +391,7 @@ CELL collect_next(CELL scan);
DECLARE_PRIMITIVE(gc); DECLARE_PRIMITIVE(gc);
DECLARE_PRIMITIVE(gc_stats); DECLARE_PRIMITIVE(gc_stats);
DECLARE_PRIMITIVE(gc_reset);
DECLARE_PRIMITIVE(become); DECLARE_PRIMITIVE(become);
CELL find_all_words(void); CELL find_all_words(void);

View File

@ -186,4 +186,5 @@ void *primitives[] = {
primitive_resize_float_array, primitive_resize_float_array,
primitive_dll_validp, primitive_dll_validp,
primitive_unimplemented, primitive_unimplemented,
primitive_gc_reset,
}; };