vm: clean up gc events, remove -verbosegc switch, fix compaction bug

db4
Slava Pestov 2009-10-27 21:31:28 -05:00
parent a7b55e7068
commit a1aac42786
16 changed files with 110 additions and 165 deletions

View File

@ -10,10 +10,15 @@ IN: tools.memory
<PRIVATE
: commas ( n -- str )
number>string
reverse 3 group "," join reverse ;
: kilobytes ( n -- str )
1024 /i number>string
dup length 4 > [ 3 cut* "," glue ] when
" KB" append ;
1024 /i commas " KB" append ;
: micros>string ( n -- str )
commas " microseconds" append ;
: fancy-table. ( obj alist -- )
[ [ nip first ] [ second call( obj -- str ) ] 2bi 2array ] with map
@ -97,50 +102,23 @@ PRIVATE>
enable-gc-events [ ] [ disable-gc-events drop ] cleanup
disable-gc-events byte-array>gc-event-array ; inline
: generation-sizes-before ( events -- sizes )
[
: gc-op-string ( op -- string )
{
[ start-time>> ]
[ nursery-size-before>> ]
[ aging-size-before>> ]
[ tenured-size-before>> ]
[ code-size-before>> ]
} cleave 5 narray
] { } map-as ;
{ collect-nursery-op [ "copying from nursery" ] }
{ collect-aging-op [ "copying from aging" ] }
{ collect-to-tenured-op [ "copying to tenured" ] }
{ collect-full-op [ "mark and sweep" ] }
{ collect-compact-op [ "mark and compact" ] }
{ collect-growing-heap-op [ "grow heap" ] }
} case ;
: generation-sizes-after ( events -- sizes )
[
{
[ start-time>> ]
[ nursery-size-after>> ]
[ aging-size-after>> ]
[ tenured-size-after>> ]
[ code-size-after>> ]
} cleave 5 narray
] { } map-as ;
: space-reclaimed ( event -- bytes )
[ data-heap-before>> ] [ data-heap-after>> ] bi
[ [ nursery>> ] [ aging>> ] [ tenured>> ] tri [ occupied>> ] tri@ + + ] bi@ - ;
: reclaimed-space ( events -- sizes )
[
[ start-time>> ] [
: gc-event. ( event -- )
{
[ [ nursery-size-before>> ] [ nursery-size-after>> ] bi - ]
[ [ aging-size-before>> ] [ aging-size-after>> ] bi - ]
[ [ tenured-size-before>> ] [ tenured-size-after>> ] bi - ]
[ [ code-size-before>> ] [ code-size-after>> ] bi - ]
} cleave
+ + +
] bi 2array
] { } map-as ;
: allocated-space ( events -- sizes )
2 <sliced-clumps> [
[ second start-time>> ] [
{
[ [ second nursery-size-before>> ] [ first nursery-size-after>> ] bi - ]
[ [ second aging-size-before>> ] [ first aging-size-after>> ] bi - ]
[ [ second tenured-size-before>> ] [ first tenured-size-after>> ] bi - ]
[ [ second code-size-before>> ] [ first code-size-after>> ] bi - ]
} cleave
+ + +
] bi 2array
] { } map-as ;
{ "Event type:" [ op>> gc-op-string ] }
{ "Total time:" [ total-time>> micros>string ] }
{ "Space reclaimed:" [ space-reclaimed kilobytes ] }
} fancy-table. ;

View File

@ -29,31 +29,6 @@ collect-full-op
collect-compact-op
collect-growing-heap-op ;
STRUCT: gc-event
{ op uint }
{ nursery-size-before cell }
{ aging-size-before cell }
{ tenured-size-before cell }
{ tenured-free-block-count-before cell }
{ code-size-before cell }
{ code-free-block-count-before cell }
{ nursery-size-after cell }
{ aging-size-after cell }
{ tenured-size-after cell }
{ tenured-free-block-count-after cell }
{ code-size-after cell }
{ code-free-block-count-after cell }
{ cards-scanned cell }
{ decks-scanned cell }
{ code-blocks-scanned cell }
{ start-time ulonglong }
{ total-time cell }
{ card-scan-time cell }
{ code-scan-time cell }
{ data-sweep-time cell }
{ code-sweep-time cell }
{ compaction-time cell } ;
STRUCT: copying-sizes
{ size cell }
{ occupied cell }
@ -73,3 +48,20 @@ STRUCT: data-heap-room
{ cards cell }
{ decks cell }
{ mark-stack cell } ;
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 }
{ decks-scanned cell }
{ code-blocks-scanned cell }
{ start-time ulonglong }
{ total-time cell }
{ card-scan-time cell }
{ code-scan-time cell }
{ data-sweep-time cell }
{ code-sweep-time cell }
{ compaction-time cell } ;

View File

@ -13,14 +13,14 @@ struct growable_byte_array {
void trim();
};
template<typename T> byte_array *factor_vm::byte_array_from_value(T *value)
template<typename Type> byte_array *factor_vm::byte_array_from_value(Type *value)
{
return byte_array_from_values(value,1);
}
template<typename T> byte_array *factor_vm::byte_array_from_values(T *values, cell len)
template<typename Type> byte_array *factor_vm::byte_array_from_values(Type *values, cell len)
{
cell size = sizeof(T) * len;
cell size = sizeof(Type) * len;
byte_array *data = allot_uninitialized_array<byte_array>(size);
memcpy(data->data<char>(),values,size);
return data;

View File

@ -196,7 +196,7 @@ void factor_vm::primitive_modify_code_heap()
update_code_heap_words();
}
void factor_vm::primitive_code_room()
code_heap_room factor_vm::code_room()
{
code_heap_room room;
@ -206,6 +206,12 @@ void factor_vm::primitive_code_room()
room.contiguous_free = code->allocator->free_blocks.largest_free_block();
room.free_block_count = code->allocator->free_blocks.free_block_count;
return room;
}
void factor_vm::primitive_code_room()
{
code_heap_room room = code_room();
dpush(tag<byte_array>(byte_array_from_value(&room)));
}

View File

@ -55,10 +55,12 @@ struct compaction_sizer {
cell operator()(object *obj)
{
if(obj->free_p() || obj->h.hi_tag() != TUPLE_TYPE)
return obj->size();
else
if(!forwarding_map->marked_p(obj))
return forwarding_map->unmarked_space_starting_at(obj);
else if(obj->h.hi_tag() == TUPLE_TYPE)
return align(tuple_size_with_forwarding(forwarding_map,obj),data_alignment);
else
return obj->size();
}
};

View File

@ -201,7 +201,7 @@ void factor_vm::primitive_size()
box_unsigned_cell(object_size(dpop()));
}
void factor_vm::primitive_data_room()
data_heap_room factor_vm::data_room()
{
data_heap_room room;
@ -220,6 +220,12 @@ void factor_vm::primitive_data_room()
room.decks = data->decks_end - data->decks;
room.mark_stack = data->tenured->mark_stack.capacity();
return room;
}
void factor_vm::primitive_data_room()
{
data_heap_room room = data_room();
dpush(tag<byte_array>(byte_array_from_value(&room)));
}

View File

@ -38,7 +38,6 @@ void factor_vm::default_parameters(vm_parameters *p)
p->max_pic_size = 3;
p->fep = false;
p->verbose_gc = false;
p->signals = true;
#ifdef WINDOWS
@ -87,7 +86,6 @@ void factor_vm::init_parameters_from_args(vm_parameters *p, int argc, vm_char **
else if(factor_arg(arg,STRING_LITERAL("-callbacks=%d"),&p->callback_size));
else if(STRCMP(arg,STRING_LITERAL("-fep")) == 0) p->fep = true;
else if(STRCMP(arg,STRING_LITERAL("-nosignals")) == 0) p->signals = false;
else if(STRCMP(arg,STRING_LITERAL("-verbosegc")) == 0) p->verbose_gc = true;
else if(STRNCMP(arg,STRING_LITERAL("-i="),3) == 0) p->image_path = arg + 3;
else if(STRCMP(arg,STRING_LITERAL("-console")) == 0) p->console = true;
}
@ -142,8 +140,6 @@ void factor_vm::init_factor(vm_parameters *p)
if(p->signals)
init_signals();
verbose_gc = p->verbose_gc;
if(p->console)
open_console();

View File

@ -108,10 +108,8 @@ cell free_list::largest_free_block()
{
if(large_blocks.size())
{
large_block_set::iterator end = large_blocks.end();
free_heap_block *block = *end;
large_blocks.erase(end);
return block->size();
large_block_set::reverse_iterator last = large_blocks.rbegin();
return (*last)->size();
}
else
{

View File

@ -14,6 +14,7 @@ template<typename Block> struct free_list_allocator {
Block *first_block();
Block *last_block();
Block *next_block_after(Block *block);
Block *next_allocated_block_after(Block *block);
bool can_allot_p(cell size);
Block *allot(cell size);
void free(Block *block);
@ -58,6 +59,20 @@ template<typename Block> Block *free_list_allocator<Block>::next_block_after(Blo
return (Block *)((cell)block + block->size());
}
template<typename Block> Block *free_list_allocator<Block>::next_allocated_block_after(Block *block)
{
while(block != this->last_block() && block->free_p())
{
free_heap_block *free_block = (free_heap_block *)block;
block = (object *)((cell)free_block + free_block->size());
}
if(block == this->last_block())
return NULL;
else
return block;
}
template<typename Block> bool free_list_allocator<Block>::can_allot_p(cell size)
{
return free_blocks.can_allot_p(size);

View File

@ -15,12 +15,8 @@ gc_event::gc_event(gc_op op_, factor_vm *parent) :
code_sweep_time(0),
compaction_time(0)
{
nursery_size_before = parent->nursery.occupied_space();
aging_size_before = parent->data->aging->occupied_space();
tenured_size_before = parent->data->tenured->occupied_space();
tenured_free_block_count_before = parent->data->tenured->free_blocks.free_block_count;
code_size_before = parent->code->allocator->occupied_space();
code_free_block_count_before = parent->code->allocator->free_blocks.free_block_count;
data_heap_before = parent->data_room();
code_heap_before = parent->code_room();
start_time = current_micros();
}
@ -79,44 +75,11 @@ void gc_event::ended_compaction()
void gc_event::ended_gc(factor_vm *parent)
{
nursery_size_after = parent->nursery.occupied_space();
aging_size_after = parent->data->aging->occupied_space();
tenured_size_after = parent->data->tenured->occupied_space();
tenured_free_block_count_after = parent->data->tenured->free_blocks.free_block_count;
code_size_after = parent->code->allocator->occupied_space();
code_free_block_count_after = parent->code->allocator->free_blocks.free_block_count;
data_heap_after = parent->data_room();
code_heap_after = parent->code_room();
total_time = current_micros() - start_time;
}
std::ostream &operator<<(std::ostream &out, const gc_event *event)
{
out << "<event\n"
<< " op = '" << event->op << "'\n"
<< " nursery_size_before = '" << event->nursery_size_before << "'\n"
<< " aging_size_before = '" << event->aging_size_before << "'\n"
<< " tenured_size_before = '" << event->tenured_size_before << "'\n"
<< " tenured_free_block_count_before = '" << event->tenured_free_block_count_before << "'\n"
<< " code_size_before = '" << event->code_size_before << "'\n"
<< " code_free_block_count_before = '" << event->code_free_block_count_before << "'\n"
<< " nursery_size_after = '" << event->nursery_size_after << "'\n"
<< " aging_size_after = '" << event->aging_size_after << "'\n"
<< " tenured_size_after = '" << event->tenured_size_after << "'\n"
<< " tenured_free_block_count_after = '" << event->tenured_free_block_count_after << "'\n"
<< " code_size_after = '" << event->code_size_after << "'\n"
<< " code_free_block_count_after = '" << event->code_free_block_count_after << "'\n"
<< " cards_scanned = '" << event->cards_scanned << "'\n"
<< " decks_scanned = '" << event->decks_scanned << "'\n"
<< " code_blocks_scanned = '" << event->code_blocks_scanned << "'\n"
<< " start_time = '" << event->start_time << "'\n"
<< " total_time = '" << event->total_time << "'\n"
<< " card_scan_time = '" << event->card_scan_time << "'\n"
<< " code_scan_time = '" << event->code_scan_time << "'\n"
<< " data_sweep_time = '" << event->data_sweep_time << "'\n"
<< " code_sweep_time = '" << event->code_sweep_time << "'\n"
<< " compaction_time = '" << event->compaction_time << "' />";
return out;
}
gc_state::gc_state(gc_op op_, factor_vm *parent) : op(op_), start_time(current_micros())
{
event = new gc_event(op,parent);
@ -131,7 +94,6 @@ gc_state::~gc_state()
void factor_vm::end_gc()
{
current_gc->event->ended_gc(this);
if(verbose_gc) std::cout << current_gc->event << std::endl;
if(gc_events) gc_events->push_back(*current_gc->event);
delete current_gc->event;
current_gc->event = NULL;
@ -354,7 +316,7 @@ void factor_vm::primitive_disable_gc_events()
{
if(gc_events)
{
byte_array *data = byte_array_from_values(&gc_events->front(),gc_events->size());
byte_array *data = byte_array_from_values(&gc_events->first(),gc_events->size());
dpush(tag<byte_array>(data));
delete gc_events;

View File

@ -12,18 +12,10 @@ enum gc_op {
struct gc_event {
gc_op op;
cell nursery_size_before;
cell aging_size_before;
cell tenured_size_before;
cell tenured_free_block_count_before;
cell code_size_before;
cell code_free_block_count_before;
cell nursery_size_after;
cell aging_size_after;
cell tenured_size_after;
cell tenured_free_block_count_after;
cell code_size_after;
cell code_free_block_count_after;
data_heap_room data_heap_before;
code_heap_room code_heap_before;
data_heap_room data_heap_after;
code_heap_room code_heap_after;
cell cards_scanned;
cell decks_scanned;
cell code_blocks_scanned;

View File

@ -35,7 +35,6 @@ struct vm_parameters {
cell young_size, aging_size, tenured_size;
cell code_size;
bool fep;
bool verbose_gc;
bool console;
bool signals;
cell max_pic_size;

View File

@ -154,6 +154,20 @@ template<typename Block> struct mark_bits {
#endif
return new_block;
}
/* Find the next allocated block without calling size() on unmarked
objects. */
cell unmarked_space_starting_at(Block *original)
{
char *start = (char *)original;
char *scan = start;
char *end = (char *)(this->start + this->size);
while(scan != end && !marked_p((Block *)scan))
scan += block_granularity;
return scan - start;
}
};
}

View File

@ -59,6 +59,7 @@ namespace factor
#include "aging_space.hpp"
#include "tenured_space.hpp"
#include "data_heap.hpp"
#include "code_heap.hpp"
#include "gc.hpp"
#include "debug.hpp"
#include "strings.hpp"
@ -68,7 +69,6 @@ namespace factor
#include "io.hpp"
#include "image.hpp"
#include "alien.hpp"
#include "code_heap.hpp"
#include "callbacks.hpp"
#include "vm.hpp"
#include "tagged.hpp"

View File

@ -20,30 +20,16 @@ struct tenured_space : free_list_allocator<object> {
return NULL;
}
object *first_allocated_block_after(object *block)
{
while(block != this->last_block() && block->free_p())
{
free_heap_block *free_block = (free_heap_block *)block;
block = (object *)((cell)free_block + free_block->size());
}
if(block == this->last_block())
return NULL;
else
return block;
}
cell first_object()
{
return (cell)first_allocated_block_after(this->first_block());
return (cell)next_allocated_block_after(this->first_block());
}
cell next_object_after(cell scan)
{
cell size = ((object *)scan)->size();
object *next = (object *)(scan + size);
return (cell)first_allocated_block_after(next);
return (cell)next_allocated_block_after(next);
}
void clear_mark_bits()

View File

@ -46,9 +46,6 @@ struct factor_vm
/* GC is off during heap walking */
bool gc_off;
/* GC logging */
bool verbose_gc;
/* Data heap */
data_heap *data;
@ -223,6 +220,7 @@ struct factor_vm
void set_data_heap(data_heap *data_);
void init_data_heap(cell young_size, cell aging_size, cell tenured_size);
void primitive_size();
data_heap_room data_room();
void primitive_data_room();
void begin_scan();
void end_scan();
@ -502,6 +500,7 @@ struct factor_vm
void update_code_heap_words_and_literals();
void relocate_code_heap();
void primitive_modify_code_heap();
code_heap_room code_room();
void primitive_code_room();
void primitive_strip_stack_traces();