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.
! See http://factorcode.org/license.txt for BSD license.
USING: kernel math math.vectors memory io io.styles prettyprint
namespaces system sequences assocs ;
namespaces system sequences splitting assocs strings ;
IN: tools.time
: benchmark ( quot -- gctime runtime )
millis >r call millis r> - ; inline
: stats. ( data -- )
{
"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
: simple-table. ( values -- )
standard-table-style [
[
[
[ [ write ] with-cell ] [ pprint-cell ] bi*
[
dup string?
[ [ write ] with-cell ]
[ pprint-cell ]
if
] each
] with-row
] assoc-each
] each
] 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 -- )
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);
}
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,
CELL young_size,
CELL aging_size,
@ -158,17 +165,13 @@ void init_data_heap(CELL gens,
extra_roots_region = alloc_segment(getpagesize());
extra_roots = extra_roots_region->start - CELLS;
nursery_gc_time = 0;
nursery_collections = 0;
aging_gc_time = 0;
aging_collections = 0;
tenured_gc_time = 0;
tenured_collections = 0;
secure_gc = secure_gc_;
gc_reset();
cards_scanned = 0;
decks_scanned = 0;
code_heap_scans = 0;
bytes_copied = 0;
secure_gc = secure_gc_;
}
/* Size of the object pointed to by a tagged pointer */
@ -312,14 +315,8 @@ void collect_card(F_CARD *ptr, CELL gen, CELL here)
F_CARD c = *ptr;
CELL offset = (c & CARD_BASE_MASK);
if(offset == CARD_BASE_MASK)
if(offset != CARD_BASE_MASK)
{
/* if(c == 0xff)
critical_error("bad card",(CELL)ptr);
else */
return;
}
CELL card_scan = (CELL)CARD_TO_ADDR(ptr) + offset;
CELL card_end = (CELL)CARD_TO_ADDR(ptr + 1);
@ -328,6 +325,7 @@ void collect_card(F_CARD *ptr, CELL gen, CELL here)
cards_scanned++;
}
}
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);
allot_barrier(newspace->here);
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);
return newpointer;
}
@ -641,7 +643,7 @@ CELL collect_next(CELL scan)
INLINE void reset_generation(CELL i)
{
F_ZONE *z = (i == NURSERY ? &nursery : &data_heap->generations[i]);
bytes_collected += (z->here - z->start);
z->here = z->start;
if(secure_gc)
memset((void*)z->start,69,z->size);
@ -652,7 +654,9 @@ their allocation pointers and cards reset. */
void reset_generations(CELL from, CELL to)
{
CELL i;
for(i = from; i <= to; i++) reset_generation(i);
for(i = from; i <= to; i++)
reset_generation(i);
clear_cards(from,to);
}
@ -698,6 +702,13 @@ void begin_gc(CELL requested_bytes)
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)
{
dealloc_data_heap(old_data_heap);
@ -712,28 +723,12 @@ void end_gc(CELL gc_elapsed)
old-school Cheney collector */
if(collecting_gen != NURSERY)
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
{
/* all generations up to and including the one
collected are now empty */
reset_generations(NURSERY,collecting_gen);
nursery_collections++;
nursery_gc_time += gc_elapsed;
}
if(collecting_gen == TENURED)
@ -852,24 +847,38 @@ DEFINE_PRIMITIVE(gc)
gc();
}
/* Push total time spent on GC */
DEFINE_PRIMITIVE(gc_stats)
{
CELL array = tag_object(allot_array(ARRAY_TYPE,11,F));
REGISTER_ROOT(array);
set_array_nth(untag_object(array),0,allot_cell(nursery_gc_time));
set_array_nth(untag_object(array),1,allot_cell(nursery_collections));
set_array_nth(untag_object(array),2,allot_cell(aging_gc_time));
set_array_nth(untag_object(array),3,allot_cell(aging_collections));
set_array_nth(untag_object(array),4,allot_cell(tenured_gc_time));
set_array_nth(untag_object(array),5,allot_cell(tenured_collections));
set_array_nth(untag_object(array),6,tag_bignum(long_long_to_bignum(cards_scanned)));
set_array_nth(untag_object(array),7,tag_bignum(long_long_to_bignum(decks_scanned)));
set_array_nth(untag_object(array),8,allot_cell(code_heap_scans));
set_array_nth(untag_object(array),9,tag_bignum(long_long_to_bignum(bytes_copied)));
set_array_nth(untag_object(array),10,tag_bignum(long_long_to_bignum(bytes_collected)));
UNREGISTER_ROOT(array);
dpush(array);
GROWABLE_ARRAY(stats);
CELL i;
CELL total_gc_time = 0;
for(i = 0; i < MAX_GEN_COUNT; i++)
{
F_GC_STATS *s = &gc_stats[i];
GROWABLE_ADD(stats,allot_cell(s->collections));
GROWABLE_ADD(stats,allot_cell(s->gc_time));
GROWABLE_ADD(stats,allot_cell(s->max_gc_time));
GROWABLE_ADD(stats,allot_cell(s->collections == 0 ? 0 : s->gc_time / s->collections));
GROWABLE_ADD(stats,allot_cell(s->object_count));
GROWABLE_ADD(stats,tag_bignum(long_long_to_bignum(s->bytes_copied)));
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)

View File

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

View File

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