vm: parameterize sampling rate
parent
43c832c991
commit
30ed9b535b
|
@ -1,19 +1,23 @@
|
||||||
! (c)2011 Joe Groff bsd license
|
! (c)2011 Joe Groff bsd license
|
||||||
USING: assocs calendar continuations kernel math.statistics
|
USING: assocs calendar continuations kernel math.statistics
|
||||||
namespaces sequences tools.profiler.sampling.private ;
|
math namespaces sequences tools.profiler.sampling.private ;
|
||||||
IN: tools.profiler.sampling
|
IN: tools.profiler.sampling
|
||||||
|
|
||||||
: TIME-PER-SAMPLE ( -- n ) 1 milliseconds ; inline
|
|
||||||
|
|
||||||
SYMBOL: raw-profile-data
|
SYMBOL: raw-profile-data
|
||||||
|
SYMBOL: samples-per-second
|
||||||
|
|
||||||
|
CONSTANT: default-samples-per-second 1000
|
||||||
|
|
||||||
: get-raw-profile-data ( -- data )
|
: get-raw-profile-data ( -- data )
|
||||||
raw-profile-data get-global [ "No profile data" throw ] unless* ;
|
raw-profile-data get-global [ "No profile data" throw ] unless* ;
|
||||||
|
|
||||||
: profile ( quot -- )
|
: profile* ( rate quot -- )
|
||||||
t profiling [ f profiling ] [ ] cleanup
|
[ [ samples-per-second set-global ] [ profiling ] bi ] dip
|
||||||
|
[ 0 profiling ] [ ] cleanup
|
||||||
(get-samples) raw-profile-data set-global ; inline
|
(get-samples) raw-profile-data set-global ; inline
|
||||||
|
|
||||||
|
: profile ( quot -- ) default-samples-per-second swap profile* ; inline
|
||||||
|
|
||||||
: total-sample-count ( sample -- count ) first ;
|
: total-sample-count ( sample -- count ) first ;
|
||||||
: gc-sample-count ( sample -- count ) second ;
|
: gc-sample-count ( sample -- count ) second ;
|
||||||
: foreign-sample-count ( sample -- count ) third ;
|
: foreign-sample-count ( sample -- count ) third ;
|
||||||
|
@ -22,7 +26,7 @@ SYMBOL: raw-profile-data
|
||||||
: sample-callstack ( sample -- array ) 5 swap nth ;
|
: sample-callstack ( sample -- array ) 5 swap nth ;
|
||||||
|
|
||||||
: samples>time ( samples -- time )
|
: samples>time ( samples -- time )
|
||||||
TIME-PER-SAMPLE time* ;
|
samples-per-second get-global / seconds ;
|
||||||
|
|
||||||
: (total-time) ( samples -- n )
|
: (total-time) ( samples -- n )
|
||||||
[ total-sample-count ] map-sum samples>time ;
|
[ total-sample-count ] map-sum samples>time ;
|
||||||
|
|
|
@ -157,8 +157,8 @@ void factor_vm::start_sampling_profiler_timer()
|
||||||
{
|
{
|
||||||
struct itimerval timer;
|
struct itimerval timer;
|
||||||
memset((void*)&timer, 0, sizeof(struct itimerval));
|
memset((void*)&timer, 0, sizeof(struct itimerval));
|
||||||
timer.it_value.tv_usec = 1000000/FACTOR_PROFILE_SAMPLES_PER_SECOND;
|
timer.it_value.tv_usec = 1000000/samples_per_second;
|
||||||
timer.it_interval.tv_usec = 1000000/FACTOR_PROFILE_SAMPLES_PER_SECOND;
|
timer.it_interval.tv_usec = 1000000/samples_per_second;
|
||||||
setitimer(ITIMER_REAL, &timer, NULL);
|
setitimer(ITIMER_REAL, &timer, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -308,12 +308,12 @@ void factor_vm::sampler_thread_loop()
|
||||||
assert(QueryPerformanceFrequency(&units_per_second));
|
assert(QueryPerformanceFrequency(&units_per_second));
|
||||||
|
|
||||||
assert(QueryPerformanceCounter(&counter));
|
assert(QueryPerformanceCounter(&counter));
|
||||||
counter.QuadPart *= FACTOR_PROFILE_SAMPLES_PER_SECOND;
|
counter.QuadPart *= samples_per_second;
|
||||||
while (atomic::fence(), sampling_profiler_p)
|
while (atomic::fence(), sampling_profiler_p)
|
||||||
{
|
{
|
||||||
SwitchToThread();
|
SwitchToThread();
|
||||||
assert(QueryPerformanceCounter(&new_counter));
|
assert(QueryPerformanceCounter(&new_counter));
|
||||||
new_counter.QuadPart *= FACTOR_PROFILE_SAMPLES_PER_SECOND;
|
new_counter.QuadPart *= samples_per_second;
|
||||||
cell samples = 0;
|
cell samples = 0;
|
||||||
while (new_counter.QuadPart - counter.QuadPart > units_per_second.QuadPart) {
|
while (new_counter.QuadPart - counter.QuadPart > units_per_second.QuadPart) {
|
||||||
// We would have to suspend the thread to sample the PC
|
// We would have to suspend the thread to sample the PC
|
||||||
|
@ -348,7 +348,7 @@ void factor_vm::end_sampling_profiler_timer()
|
||||||
sampling_profiler_p = false;
|
sampling_profiler_p = false;
|
||||||
atomic::fence();
|
atomic::fence();
|
||||||
DWORD wait_result = WaitForSingleObject(sampler_thread,
|
DWORD wait_result = WaitForSingleObject(sampler_thread,
|
||||||
3000/FACTOR_PROFILE_SAMPLES_PER_SECOND);
|
3000/samples_per_second);
|
||||||
if (wait_result != WAIT_OBJECT_0)
|
if (wait_result != WAIT_OBJECT_0)
|
||||||
TerminateThread(sampler_thread, 0);
|
TerminateThread(sampler_thread, 0);
|
||||||
sampler_thread = NULL;
|
sampler_thread = NULL;
|
||||||
|
|
|
@ -57,13 +57,14 @@ void factor_vm::record_callstack_sample(cell *begin, cell *end)
|
||||||
*end = sample_callstacks.size();
|
*end = sample_callstacks.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void factor_vm::set_sampling_profiler(bool sampling_p)
|
void factor_vm::set_sampling_profiler(int rate)
|
||||||
{
|
{
|
||||||
|
bool sampling_p = !!rate;
|
||||||
if (sampling_p == sampling_profiler_p)
|
if (sampling_p == sampling_profiler_p)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (sampling_p)
|
if (sampling_p)
|
||||||
start_sampling_profiler();
|
start_sampling_profiler(rate);
|
||||||
else
|
else
|
||||||
end_sampling_profiler();
|
end_sampling_profiler();
|
||||||
}
|
}
|
||||||
|
@ -78,12 +79,13 @@ void factor_vm::clear_samples()
|
||||||
sample_callstacks.swap(sample_callstack_graveyard);
|
sample_callstacks.swap(sample_callstack_graveyard);
|
||||||
}
|
}
|
||||||
|
|
||||||
void factor_vm::start_sampling_profiler()
|
void factor_vm::start_sampling_profiler(int rate)
|
||||||
{
|
{
|
||||||
|
samples_per_second = rate;
|
||||||
safepoint_sample_counts.clear();
|
safepoint_sample_counts.clear();
|
||||||
clear_samples();
|
clear_samples();
|
||||||
samples.reserve(10*FACTOR_PROFILE_SAMPLES_PER_SECOND);
|
samples.reserve(10*rate);
|
||||||
sample_callstacks.reserve(100*FACTOR_PROFILE_SAMPLES_PER_SECOND);
|
sample_callstacks.reserve(100*rate);
|
||||||
sampling_profiler_p = true;
|
sampling_profiler_p = true;
|
||||||
start_sampling_profiler_timer();
|
start_sampling_profiler_timer();
|
||||||
}
|
}
|
||||||
|
@ -98,7 +100,7 @@ void factor_vm::end_sampling_profiler()
|
||||||
|
|
||||||
void factor_vm::primitive_sampling_profiler()
|
void factor_vm::primitive_sampling_profiler()
|
||||||
{
|
{
|
||||||
set_sampling_profiler(to_boolean(ctx->pop()));
|
set_sampling_profiler(to_fixnum(ctx->pop()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void factor_vm::primitive_get_samples()
|
void factor_vm::primitive_get_samples()
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
namespace factor
|
namespace factor
|
||||||
{
|
{
|
||||||
|
|
||||||
#define FACTOR_PROFILE_SAMPLES_PER_SECOND 1000
|
|
||||||
|
|
||||||
struct profiling_sample_count
|
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
|
||||||
|
|
|
@ -63,6 +63,7 @@ struct factor_vm
|
||||||
/* Is profiling enabled? */
|
/* Is profiling enabled? */
|
||||||
bool counting_profiler_p;
|
bool counting_profiler_p;
|
||||||
volatile bool sampling_profiler_p;
|
volatile bool sampling_profiler_p;
|
||||||
|
int samples_per_second;
|
||||||
|
|
||||||
/* Global variables used to pass fault handler state from signal handler
|
/* Global variables used to pass fault handler state from signal handler
|
||||||
to VM */
|
to VM */
|
||||||
|
@ -194,9 +195,9 @@ struct factor_vm
|
||||||
void clear_samples();
|
void clear_samples();
|
||||||
void record_sample();
|
void record_sample();
|
||||||
void record_callstack_sample(cell *begin, cell *end);
|
void record_callstack_sample(cell *begin, cell *end);
|
||||||
void start_sampling_profiler();
|
void start_sampling_profiler(int rate);
|
||||||
void end_sampling_profiler();
|
void end_sampling_profiler();
|
||||||
void set_sampling_profiler(bool sampling);
|
void set_sampling_profiler(int rate);
|
||||||
void enqueue_safepoint_sample(cell samples, cell pc, bool foreign_thread_p);
|
void enqueue_safepoint_sample(cell samples, cell pc, bool foreign_thread_p);
|
||||||
void primitive_sampling_profiler();
|
void primitive_sampling_profiler();
|
||||||
void primitive_get_samples();
|
void primitive_get_samples();
|
||||||
|
|
Loading…
Reference in New Issue