So that you don't need a new method for each gc phase to time.
! Copyright (C) 2005, 2011 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
-USING: accessors arrays assocs binary-search classes
-classes.struct combinators combinators.smart continuations fry
-generalizations generic grouping io io.styles kernel make math
-math.order math.parser math.statistics memory layouts namespaces
-parser prettyprint sequences sequences.generalizations sorting
-splitting strings system vm words hints hashtables ;
+USING: accessors arrays assocs binary-search classes classes.struct
+combinators combinators.smart continuations fry grouping hashtables
+hints io io.styles kernel layouts math math.order math.parser
+math.statistics memory namespaces prettyprint sequences
+sequences.generalizations sorting vm ;
IN: tools.memory
<PRIVATE
: gc-stats. ( -- )
gc-events get compute-gc-stats gc-stats-table simple-table. ;
+: sum-phase-times ( events phase -- n )
+ '[ times>> _ swap nth ] map-sum nanos>string ; inline
+
: gc-summary. ( -- )
gc-events get {
{ "Collections:" [ length commas ] }
{ "Decks scanned:" [ [ decks-scanned>> ] map-sum commas ] }
{ "Code blocks scanned:" [ [ code-blocks-scanned>> ] map-sum commas ] }
{ "Total time:" [ [ total-time>> ] map-sum nanos>string ] }
- { "Card scan time:" [ [ card-scan-time>> ] map-sum nanos>string ] }
- { "Code block scan time:" [ [ code-scan-time>> ] map-sum nanos>string ] }
- { "Data heap sweep time:" [ [ data-sweep-time>> ] map-sum nanos>string ] }
- { "Code heap sweep time:" [ [ code-sweep-time>> ] map-sum nanos>string ] }
- { "Compaction time:" [ [ compaction-time>> ] map-sum nanos>string ] }
+ { "Card scan time:" [ PHASE-CARD-SCAN sum-phase-times ] }
+ { "Code block scan time:" [ PHASE-CODE-SCAN sum-phase-times ] }
+ { "Data heap sweep time:" [ PHASE-DATA-SWEEP sum-phase-times ] }
+ { "Code heap sweep time:" [ PHASE-CODE-SWEEP sum-phase-times ] }
+ { "Data compaction time:" [ PHASE-DATA-COMPACTION sum-phase-times ] }
} object-table. ;
SINGLETONS: +unoptimized+ +optimized+ +profiling+ +pic+ ;
{ decks cell_t }
{ mark-stack cell_t } ;
+CONSTANT: PHASE-CARD-SCAN 0
+CONSTANT: PHASE-CODE-SCAN 1
+CONSTANT: PHASE-DATA-SWEEP 2
+CONSTANT: PHASE-CODE-SWEEP 3
+CONSTANT: PHASE-DATA-COMPACTION 4
+
+! gc-event should be kept in sync with:
+! vm/gc.hpp
STRUCT: gc-event
-{ op uint }
-{ data-heap-before data-heap-room }
-{ code-heap-before mark-sweep-sizes }
-{ data-heap-after data-heap-room }
-{ code-heap-after mark-sweep-sizes }
-{ cards-scanned cell_t }
-{ decks-scanned cell_t }
-{ code-blocks-scanned cell_t }
-{ start-time ulonglong }
-{ total-time cell_t }
-{ card-scan-time cell_t }
-{ code-scan-time cell_t }
-{ data-sweep-time cell_t }
-{ code-sweep-time cell_t }
-{ compaction-time cell_t }
-{ temp-time ulonglong } ;
+ { op uint }
+ { data-heap-before data-heap-room }
+ { code-heap-before mark-sweep-sizes }
+ { data-heap-after data-heap-room }
+ { code-heap-after mark-sweep-sizes }
+ { cards-scanned cell_t }
+ { decks-scanned cell_t }
+ { code-blocks-scanned cell_t }
+ { start-time ulonglong }
+ { total-time cell_t }
+ { times cell_t[5] }
+ { temp-time ulonglong } ;
! gc-info should be kept in sync with:
! vm/gc_info.hpp
if (event)
event->reset_timer();
visitor.visit_cards(data->tenured, card_points_to_aging, 0xff);
- if (event)
- event->ended_card_scan(visitor.cards_scanned, visitor.decks_scanned);
+ if (event) {
+ event->ended_phase(PHASE_CARD_SCAN);
+ event->cards_scanned += visitor.cards_scanned;
+ event->decks_scanned += visitor.decks_scanned;
+ }
if (event)
event->reset_timer();
visitor.visit_code_heap_roots(&code->points_to_aging);
- if (event)
- event->ended_code_scan(code->points_to_aging.size());
-
+ if (event) {
+ event->ended_phase(PHASE_CODE_SCAN);
+ event->code_blocks_scanned += code->points_to_aging.size();
+ }
visitor.visit_mark_stack(&mark_stack);
}
{
code->initialize_all_blocks_set();
if (event)
- event->ended_compaction();
+ event->ended_phase(PHASE_DATA_COMPACTION);
}
void factor_vm::collect_compact() {
event->reset_timer();
data->tenured->sweep();
if (event)
- event->ended_data_sweep();
+ event->ended_phase(PHASE_DATA_SWEEP);
// After a sweep, invalidate any code heap roots which are not
// marked, so that if a block makes a tail call to a generic word,
event->reset_timer();
code->sweep();
if (event)
- event->ended_code_sweep();
+ event->ended_phase(PHASE_CODE_SWEEP);
}
void factor_vm::collect_full() {
decks_scanned(0),
code_blocks_scanned(0),
start_time(nano_count()),
- card_scan_time(0),
- code_scan_time(0),
- data_sweep_time(0),
- code_sweep_time(0),
- compaction_time(0) {
+ times{0} {
data_heap_before = parent->data_room();
code_heap_before = parent->code->allocator->as_allocator_room();
start_time = nano_count();
void gc_event::reset_timer() { temp_time = nano_count(); }
-void gc_event::ended_card_scan(cell cards_scanned_, cell decks_scanned_) {
- cards_scanned += cards_scanned_;
- decks_scanned += decks_scanned_;
- card_scan_time = (cell)(nano_count() - temp_time);
-}
-
-void gc_event::ended_code_scan(cell code_blocks_scanned_) {
- code_blocks_scanned += code_blocks_scanned_;
- code_scan_time = (cell)(nano_count() - temp_time);
-}
-
-void gc_event::ended_data_sweep() {
- data_sweep_time = (cell)(nano_count() - temp_time);
-}
-
-void gc_event::ended_code_sweep() {
- code_sweep_time = (cell)(nano_count() - temp_time);
-}
-
-void gc_event::ended_compaction() {
- compaction_time = (cell)(nano_count() - temp_time);
+void gc_event::ended_phase(gc_phase phase) {
+ times[phase] = (cell)(nano_count() - temp_time);
}
void gc_event::ended_gc(factor_vm* parent) {
COLLECT_GROWING_DATA_HEAP_OP
};
+// These are the phases of the gc cycles we record the times of.
+enum gc_phase {
+ PHASE_CARD_SCAN,
+ PHASE_CODE_SCAN,
+ PHASE_DATA_SWEEP,
+ PHASE_CODE_SWEEP,
+ PHASE_DATA_COMPACTION,
+};
+
struct gc_event {
gc_op op;
data_heap_room data_heap_before;
cell code_blocks_scanned;
uint64_t start_time;
cell total_time;
- cell card_scan_time;
- cell code_scan_time;
- cell data_sweep_time;
- cell code_sweep_time;
- cell compaction_time;
+ cell times[5];
uint64_t temp_time;
gc_event(gc_op op, factor_vm* parent);
void reset_timer();
- void ended_card_scan(cell cards_scanned_, cell decks_scanned_);
- void ended_code_scan(cell code_blocks_scanned_);
- void ended_data_sweep();
- void ended_code_sweep();
- void ended_compaction();
+ void ended_phase(gc_phase phase);
void ended_gc(factor_vm* parent);
};
visitor.visit_cards(data->tenured, card_points_to_nursery,
card_points_to_nursery);
visitor.visit_cards(data->aging, card_points_to_nursery, 0xff);
- if (event)
- event->ended_card_scan(visitor.cards_scanned, visitor.decks_scanned);
+ if (event) {
+ event->ended_phase(PHASE_CARD_SCAN);
+ event->cards_scanned += visitor.cards_scanned;
+ event->decks_scanned += visitor.decks_scanned;
+ }
if (event)
event->reset_timer();
visitor.visit_code_heap_roots(&code->points_to_nursery);
- if (event)
- event->ended_code_scan(code->points_to_nursery.size());
+ if (event) {
+ event->ended_phase(PHASE_CODE_SCAN);
+ event->code_blocks_scanned += code->points_to_nursery.size();
+ }
visitor.cheneys_algorithm(data->aging, scan);
if (event)
event->reset_timer();
visitor.visit_cards(data->tenured, card_points_to_aging, 0xff);
- if (event)
- event->ended_card_scan(visitor.cards_scanned, visitor.decks_scanned);
+ if (event) {
+ event->ended_phase(PHASE_CARD_SCAN);
+ event->cards_scanned += visitor.cards_scanned;
+ event->decks_scanned += visitor.decks_scanned;
+ }
if (event)
event->reset_timer();
visitor.visit_code_heap_roots(&code->points_to_aging);
- if (event)
- event->ended_code_scan(code->points_to_aging.size());
-
+ if (event) {
+ event->ended_phase(PHASE_CODE_SCAN);
+ event->code_blocks_scanned += code->points_to_aging.size();
+ }
visitor.visit_mark_stack(&mark_stack);
data->reset_nursery();