vm: count samples from foreign threads
On OS X it appears the mach exception thread and libdispatch queue threads occasionally get the SIGALRM from the itimer. Count those as foreign_thread_samples instead of letting the signal kill the process.db4
parent
27d7e4af53
commit
f5cdfaeb2a
|
@ -170,13 +170,19 @@ void factor_vm::enqueue_safepoint_fep()
|
|||
code->guard_safepoint();
|
||||
}
|
||||
|
||||
void factor_vm::enqueue_safepoint_sample()
|
||||
void factor_vm::enqueue_safepoint_sample(cell pc, bool foreign_thread_p)
|
||||
{
|
||||
if (sampling_profiler_p)
|
||||
{
|
||||
FACTOR_ATOMIC_ADD(&safepoint_sample_count, 1);
|
||||
if (current_gc)
|
||||
FACTOR_ATOMIC_ADD(&safepoint_gc_sample_count, 1);
|
||||
if (foreign_thread_p)
|
||||
FACTOR_ATOMIC_ADD(&safepoint_foreign_thread_sample_count, 1);
|
||||
else {
|
||||
if (current_gc)
|
||||
FACTOR_ATOMIC_ADD(&safepoint_gc_sample_count, 1);
|
||||
if (!code->seg->in_segment_p(pc))
|
||||
FACTOR_ATOMIC_ADD(&safepoint_foreign_sample_count, 1);
|
||||
}
|
||||
code->guard_safepoint();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -209,9 +209,11 @@ void sample_signal_handler(int signal, siginfo_t *siginfo, void *uap)
|
|||
{
|
||||
factor_vm *vm = current_vm_p();
|
||||
if (vm)
|
||||
vm->enqueue_safepoint_sample();
|
||||
else
|
||||
fatal_error("Foreign thread received signal", signal);
|
||||
vm->enqueue_safepoint_sample((cell)UAP_PROGRAM_COUNTER(uap), false);
|
||||
else if (thread_vms.size() == 1) {
|
||||
factor_vm *the_only_vm = thread_vms.begin()->second;
|
||||
the_only_vm->enqueue_safepoint_sample((cell)UAP_PROGRAM_COUNTER(uap), true);
|
||||
}
|
||||
}
|
||||
|
||||
void ignore_signal_handler(int signal, siginfo_t *siginfo, void *uap)
|
||||
|
|
|
@ -6,10 +6,14 @@ namespace factor
|
|||
profiling_sample::profiling_sample(factor_vm *vm,
|
||||
cell sample_count,
|
||||
cell gc_sample_count,
|
||||
cell foreign_sample_count,
|
||||
cell foreign_thread_sample_count,
|
||||
context *ctx)
|
||||
:
|
||||
sample_count(sample_count),
|
||||
gc_sample_count(gc_sample_count),
|
||||
foreign_sample_count(foreign_sample_count),
|
||||
foreign_thread_sample_count(foreign_thread_sample_count),
|
||||
ctx(ctx)
|
||||
{
|
||||
vm->record_callstack_sample(&callstack_begin, &callstack_end);
|
||||
|
@ -19,20 +23,33 @@ void factor_vm::record_sample()
|
|||
{
|
||||
cell recorded_sample_count;
|
||||
cell recorded_gc_sample_count;
|
||||
cell recorded_foreign_sample_count;
|
||||
cell recorded_foreign_thread_sample_count;
|
||||
|
||||
FACTOR_MEMORY_BARRIER();
|
||||
recorded_sample_count = safepoint_sample_count;
|
||||
recorded_gc_sample_count = safepoint_gc_sample_count;
|
||||
if (recorded_sample_count == 0 && recorded_gc_sample_count == 0)
|
||||
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
|
||||
));
|
||||
}
|
||||
|
@ -105,11 +122,13 @@ void factor_vm::primitive_get_samples()
|
|||
|
||||
for (; from_iter != samples.end(); ++from_iter, ++to_i)
|
||||
{
|
||||
data_root<array> sample(allot_array(4, 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(),1,from_unsigned_cell(from_iter->gc_sample_count));
|
||||
set_array_nth(sample.untagged(),2,allot_alien((void*)from_iter->ctx));
|
||||
set_array_nth(sample.untagged(),2,from_unsigned_cell(from_iter->foreign_sample_count));
|
||||
set_array_nth(sample.untagged(),3,from_unsigned_cell(from_iter->foreign_thread_sample_count));
|
||||
set_array_nth(sample.untagged(),4,allot_alien((void*)from_iter->ctx));
|
||||
|
||||
cell callstack_size = from_iter->callstack_end - from_iter->callstack_begin;
|
||||
data_root<array> callstack(allot_array(callstack_size,false_object),this);
|
||||
|
@ -123,7 +142,7 @@ void factor_vm::primitive_get_samples()
|
|||
for (; c_from_iter != c_from_iter_end; ++c_from_iter, ++c_to_i)
|
||||
set_array_nth(callstack.untagged(),c_to_i,(*c_from_iter)->owner);
|
||||
|
||||
set_array_nth(sample.untagged(),3,callstack.value());
|
||||
set_array_nth(sample.untagged(),5,callstack.value());
|
||||
|
||||
set_array_nth(samples_array.untagged(),to_i,sample.value());
|
||||
}
|
||||
|
|
|
@ -9,6 +9,10 @@ struct profiling_sample
|
|||
cell sample_count;
|
||||
// Number of samples taken during GC
|
||||
cell gc_sample_count;
|
||||
// Number of samples taken during foreign code execution
|
||||
cell foreign_sample_count;
|
||||
// Number of samples taken during code execution in non-Factor threads
|
||||
cell foreign_thread_sample_count;
|
||||
// Active context during sample
|
||||
context *ctx;
|
||||
/* The callstack at safepoint time. Indexes to the beginning and ending
|
||||
|
@ -18,6 +22,8 @@ struct profiling_sample
|
|||
profiling_sample(factor_vm *vm,
|
||||
cell sample_count,
|
||||
cell gc_sample_count,
|
||||
cell foreign_sample_count,
|
||||
cell foreign_thread_sample_count,
|
||||
context *ctx);
|
||||
};
|
||||
|
||||
|
|
|
@ -79,6 +79,9 @@ VM_C_API void *factor_memcpy(void *dst, void *src, size_t len);
|
|||
|
||||
#endif
|
||||
|
||||
#define FACTOR_MEMORY_BARRIER() \
|
||||
MemoryBarrier()
|
||||
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
|
||||
#define FACTOR_ATOMIC_CAS(ptr, old_val, new_val) \
|
||||
|
@ -90,6 +93,9 @@ VM_C_API void *factor_memcpy(void *dst, void *src, size_t len);
|
|||
#define FACTOR_ATOMIC_SUB(ptr, val) \
|
||||
__sync_sub_and_fetch(ptr, val)
|
||||
|
||||
#define FACTOR_MEMORY_BARRIER() \
|
||||
__sync_synchronize()
|
||||
|
||||
#else
|
||||
#error "Unsupported compiler"
|
||||
#endif
|
||||
|
|
|
@ -77,6 +77,8 @@ struct factor_vm
|
|||
std::vector<code_block*> sample_callstacks;
|
||||
volatile cell safepoint_sample_count;
|
||||
volatile cell safepoint_gc_sample_count;
|
||||
volatile cell safepoint_foreign_sample_count;
|
||||
volatile cell safepoint_foreign_thread_sample_count;
|
||||
|
||||
/* GC is off during heap walking */
|
||||
bool gc_off;
|
||||
|
@ -214,7 +216,7 @@ struct factor_vm
|
|||
void synchronous_signal_handler_impl();
|
||||
void fp_signal_handler_impl();
|
||||
void enqueue_safepoint_fep();
|
||||
void enqueue_safepoint_sample();
|
||||
void enqueue_safepoint_sample(cell pc, bool foreign_thread_p);
|
||||
void handle_safepoint();
|
||||
|
||||
// bignum
|
||||
|
|
Loading…
Reference in New Issue