vm: factor out sample counting code
parent
baebb317e4
commit
27ac4c60f4
|
@ -174,14 +174,14 @@ void factor_vm::enqueue_safepoint_sample(cell samples, cell pc, bool foreign_thr
|
||||||
{
|
{
|
||||||
if (FACTOR_MEMORY_BARRIER(), sampling_profiler_p)
|
if (FACTOR_MEMORY_BARRIER(), sampling_profiler_p)
|
||||||
{
|
{
|
||||||
FACTOR_ATOMIC_ADD(&safepoint_sample_count, samples);
|
FACTOR_ATOMIC_ADD(&safepoint_sample_counts.sample_count, samples);
|
||||||
if (foreign_thread_p)
|
if (foreign_thread_p)
|
||||||
FACTOR_ATOMIC_ADD(&safepoint_foreign_thread_sample_count, samples);
|
FACTOR_ATOMIC_ADD(&safepoint_sample_counts.foreign_thread_sample_count, samples);
|
||||||
else {
|
else {
|
||||||
if (FACTOR_MEMORY_BARRIER(), current_gc)
|
if (FACTOR_MEMORY_BARRIER(), current_gc)
|
||||||
FACTOR_ATOMIC_ADD(&safepoint_gc_sample_count, samples);
|
FACTOR_ATOMIC_ADD(&safepoint_sample_counts.gc_sample_count, samples);
|
||||||
if (pc != 0 && !code->seg->in_segment_p(pc))
|
if (pc != 0 && !code->seg->in_segment_p(pc))
|
||||||
FACTOR_ATOMIC_ADD(&safepoint_foreign_sample_count, samples);
|
FACTOR_ATOMIC_ADD(&safepoint_sample_counts.foreign_sample_count, samples);
|
||||||
}
|
}
|
||||||
code->guard_safepoint();
|
code->guard_safepoint();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,17 +3,35 @@
|
||||||
namespace factor
|
namespace factor
|
||||||
{
|
{
|
||||||
|
|
||||||
|
profiling_sample_count profiling_sample_count::record_counts() volatile
|
||||||
|
{
|
||||||
|
FACTOR_MEMORY_BARRIER();
|
||||||
|
profiling_sample_count returned(
|
||||||
|
sample_count,
|
||||||
|
gc_sample_count,
|
||||||
|
foreign_sample_count,
|
||||||
|
foreign_thread_sample_count);
|
||||||
|
FACTOR_ATOMIC_SUB(&sample_count, returned.sample_count);
|
||||||
|
FACTOR_ATOMIC_SUB(&gc_sample_count, returned.gc_sample_count);
|
||||||
|
FACTOR_ATOMIC_SUB(&foreign_sample_count, returned.foreign_sample_count);
|
||||||
|
FACTOR_ATOMIC_SUB(&foreign_thread_sample_count, returned.foreign_thread_sample_count);
|
||||||
|
return returned;
|
||||||
|
}
|
||||||
|
|
||||||
|
void profiling_sample_count::clear() volatile
|
||||||
|
{
|
||||||
|
sample_count = 0;
|
||||||
|
gc_sample_count = 0;
|
||||||
|
foreign_sample_count = 0;
|
||||||
|
foreign_thread_sample_count = 0;
|
||||||
|
FACTOR_MEMORY_BARRIER();
|
||||||
|
}
|
||||||
|
|
||||||
profiling_sample::profiling_sample(factor_vm *vm,
|
profiling_sample::profiling_sample(factor_vm *vm,
|
||||||
fixnum sample_count,
|
profiling_sample_count const &counts,
|
||||||
fixnum gc_sample_count,
|
|
||||||
fixnum foreign_sample_count,
|
|
||||||
fixnum foreign_thread_sample_count,
|
|
||||||
context *ctx)
|
context *ctx)
|
||||||
:
|
:
|
||||||
sample_count(sample_count),
|
counts(counts),
|
||||||
gc_sample_count(gc_sample_count),
|
|
||||||
foreign_sample_count(foreign_sample_count),
|
|
||||||
foreign_thread_sample_count(foreign_thread_sample_count),
|
|
||||||
ctx(ctx)
|
ctx(ctx)
|
||||||
{
|
{
|
||||||
vm->record_callstack_sample(&callstack_begin, &callstack_end);
|
vm->record_callstack_sample(&callstack_begin, &callstack_end);
|
||||||
|
@ -21,37 +39,9 @@ profiling_sample::profiling_sample(factor_vm *vm,
|
||||||
|
|
||||||
void factor_vm::record_sample()
|
void factor_vm::record_sample()
|
||||||
{
|
{
|
||||||
fixnum recorded_sample_count;
|
profiling_sample_count counts = safepoint_sample_counts.record_counts();
|
||||||
fixnum recorded_gc_sample_count;
|
if (!counts.empty())
|
||||||
fixnum recorded_foreign_sample_count;
|
samples.push_back(profiling_sample(this, counts, ctx));
|
||||||
fixnum recorded_foreign_thread_sample_count;
|
|
||||||
|
|
||||||
FACTOR_MEMORY_BARRIER();
|
|
||||||
recorded_sample_count = safepoint_sample_count;
|
|
||||||
recorded_gc_sample_count = safepoint_gc_sample_count;
|
|
||||||
recorded_foreign_sample_count = safepoint_foreign_sample_count;
|
|
||||||
recorded_foreign_thread_sample_count = safepoint_foreign_thread_sample_count;
|
|
||||||
if (recorded_sample_count
|
|
||||||
+ recorded_gc_sample_count
|
|
||||||
+ recorded_foreign_sample_count
|
|
||||||
+ recorded_foreign_thread_sample_count
|
|
||||||
== 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Another sample signal could be raised while we record these counts */
|
|
||||||
FACTOR_ATOMIC_SUB(&safepoint_sample_count, recorded_sample_count);
|
|
||||||
FACTOR_ATOMIC_SUB(&safepoint_gc_sample_count, recorded_gc_sample_count);
|
|
||||||
FACTOR_ATOMIC_SUB(&safepoint_foreign_sample_count, recorded_foreign_sample_count);
|
|
||||||
FACTOR_ATOMIC_SUB(&safepoint_foreign_thread_sample_count, recorded_foreign_thread_sample_count);
|
|
||||||
|
|
||||||
samples.push_back(profiling_sample(
|
|
||||||
this,
|
|
||||||
recorded_sample_count,
|
|
||||||
recorded_gc_sample_count,
|
|
||||||
recorded_foreign_sample_count,
|
|
||||||
recorded_foreign_thread_sample_count,
|
|
||||||
ctx
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void factor_vm::record_callstack_sample(cell *begin, cell *end)
|
void factor_vm::record_callstack_sample(cell *begin, cell *end)
|
||||||
|
@ -90,10 +80,7 @@ void factor_vm::clear_samples()
|
||||||
|
|
||||||
void factor_vm::start_sampling_profiler()
|
void factor_vm::start_sampling_profiler()
|
||||||
{
|
{
|
||||||
safepoint_sample_count = 0;
|
safepoint_sample_counts.clear();
|
||||||
safepoint_gc_sample_count = 0;
|
|
||||||
safepoint_foreign_sample_count = 0;
|
|
||||||
safepoint_foreign_thread_sample_count = 0;
|
|
||||||
clear_samples();
|
clear_samples();
|
||||||
samples.reserve(10*FACTOR_PROFILE_SAMPLES_PER_SECOND);
|
samples.reserve(10*FACTOR_PROFILE_SAMPLES_PER_SECOND);
|
||||||
sample_callstacks.reserve(100*FACTOR_PROFILE_SAMPLES_PER_SECOND);
|
sample_callstacks.reserve(100*FACTOR_PROFILE_SAMPLES_PER_SECOND);
|
||||||
|
@ -127,10 +114,10 @@ void factor_vm::primitive_get_samples()
|
||||||
{
|
{
|
||||||
data_root<array> sample(allot_array(6, false_object),this);
|
data_root<array> sample(allot_array(6, false_object),this);
|
||||||
|
|
||||||
set_array_nth(sample.untagged(),0,from_unsigned_cell(from_iter->sample_count));
|
set_array_nth(sample.untagged(),0,from_unsigned_cell(from_iter->counts.sample_count));
|
||||||
set_array_nth(sample.untagged(),1,from_unsigned_cell(from_iter->gc_sample_count));
|
set_array_nth(sample.untagged(),1,from_unsigned_cell(from_iter->counts.gc_sample_count));
|
||||||
set_array_nth(sample.untagged(),2,from_unsigned_cell(from_iter->foreign_sample_count));
|
set_array_nth(sample.untagged(),2,from_unsigned_cell(from_iter->counts.foreign_sample_count));
|
||||||
set_array_nth(sample.untagged(),3,from_unsigned_cell(from_iter->foreign_thread_sample_count));
|
set_array_nth(sample.untagged(),3,from_unsigned_cell(from_iter->counts.foreign_thread_sample_count));
|
||||||
set_array_nth(sample.untagged(),4,allot_alien((void*)from_iter->ctx));
|
set_array_nth(sample.untagged(),4,allot_alien((void*)from_iter->ctx));
|
||||||
|
|
||||||
cell callstack_size = from_iter->callstack_end - from_iter->callstack_begin;
|
cell callstack_size = from_iter->callstack_end - from_iter->callstack_begin;
|
||||||
|
|
|
@ -3,7 +3,7 @@ namespace factor
|
||||||
|
|
||||||
#define FACTOR_PROFILE_SAMPLES_PER_SECOND 1000
|
#define FACTOR_PROFILE_SAMPLES_PER_SECOND 1000
|
||||||
|
|
||||||
struct profiling_sample
|
struct profiling_sample_count
|
||||||
{
|
{
|
||||||
// Number of samples taken before the safepoint that recorded the sample
|
// Number of samples taken before the safepoint that recorded the sample
|
||||||
fixnum sample_count;
|
fixnum sample_count;
|
||||||
|
@ -13,6 +13,38 @@ struct profiling_sample
|
||||||
fixnum foreign_sample_count;
|
fixnum foreign_sample_count;
|
||||||
// Number of samples taken during code execution in non-Factor threads
|
// Number of samples taken during code execution in non-Factor threads
|
||||||
fixnum foreign_thread_sample_count;
|
fixnum foreign_thread_sample_count;
|
||||||
|
|
||||||
|
profiling_sample_count() :
|
||||||
|
sample_count(0),
|
||||||
|
gc_sample_count(0),
|
||||||
|
foreign_sample_count(0),
|
||||||
|
foreign_thread_sample_count(0) {}
|
||||||
|
|
||||||
|
profiling_sample_count(fixnum sample_count,
|
||||||
|
fixnum gc_sample_count,
|
||||||
|
fixnum foreign_sample_count,
|
||||||
|
fixnum foreign_thread_sample_count) :
|
||||||
|
sample_count(sample_count),
|
||||||
|
gc_sample_count(gc_sample_count),
|
||||||
|
foreign_sample_count(foreign_sample_count),
|
||||||
|
foreign_thread_sample_count(foreign_thread_sample_count) {}
|
||||||
|
|
||||||
|
bool empty() const
|
||||||
|
{
|
||||||
|
return sample_count
|
||||||
|
+ gc_sample_count
|
||||||
|
+ foreign_sample_count
|
||||||
|
+ foreign_thread_sample_count == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
profiling_sample_count record_counts() volatile;
|
||||||
|
void clear() volatile;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct profiling_sample
|
||||||
|
{
|
||||||
|
// Sample counts
|
||||||
|
profiling_sample_count counts;
|
||||||
// Active context during sample
|
// Active context during sample
|
||||||
context *ctx;
|
context *ctx;
|
||||||
/* The callstack at safepoint time. Indexes to the beginning and ending
|
/* The callstack at safepoint time. Indexes to the beginning and ending
|
||||||
|
@ -20,10 +52,7 @@ struct profiling_sample
|
||||||
cell callstack_begin, callstack_end;
|
cell callstack_begin, callstack_end;
|
||||||
|
|
||||||
profiling_sample(factor_vm *vm,
|
profiling_sample(factor_vm *vm,
|
||||||
fixnum sample_count,
|
profiling_sample_count const &counts,
|
||||||
fixnum gc_sample_count,
|
|
||||||
fixnum foreign_sample_count,
|
|
||||||
fixnum foreign_thread_sample_count,
|
|
||||||
context *ctx);
|
context *ctx);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -10,10 +10,6 @@ factor_vm::factor_vm() :
|
||||||
counting_profiler_p(false),
|
counting_profiler_p(false),
|
||||||
sampling_profiler_p(false),
|
sampling_profiler_p(false),
|
||||||
safepoint_fep(false),
|
safepoint_fep(false),
|
||||||
safepoint_sample_count(0),
|
|
||||||
safepoint_gc_sample_count(0),
|
|
||||||
safepoint_foreign_sample_count(0),
|
|
||||||
safepoint_foreign_thread_sample_count(0),
|
|
||||||
gc_off(false),
|
gc_off(false),
|
||||||
current_gc(NULL),
|
current_gc(NULL),
|
||||||
gc_events(NULL),
|
gc_events(NULL),
|
||||||
|
|
|
@ -75,10 +75,7 @@ struct factor_vm
|
||||||
/* State kept by the sampling profiler */
|
/* State kept by the sampling profiler */
|
||||||
std::vector<profiling_sample> samples;
|
std::vector<profiling_sample> samples;
|
||||||
std::vector<code_block*> sample_callstacks;
|
std::vector<code_block*> sample_callstacks;
|
||||||
volatile fixnum safepoint_sample_count;
|
volatile profiling_sample_count safepoint_sample_counts;
|
||||||
volatile fixnum safepoint_gc_sample_count;
|
|
||||||
volatile fixnum safepoint_foreign_sample_count;
|
|
||||||
volatile fixnum safepoint_foreign_thread_sample_count;
|
|
||||||
|
|
||||||
/* GC is off during heap walking */
|
/* GC is off during heap walking */
|
||||||
bool gc_off;
|
bool gc_off;
|
||||||
|
|
Loading…
Reference in New Issue