6 profiling_sample::profiling_sample(factor_vm *vm,
9 cell foreign_sample_count,
10 cell foreign_thread_sample_count,
13 sample_count(sample_count),
14 gc_sample_count(gc_sample_count),
15 foreign_sample_count(foreign_sample_count),
16 foreign_thread_sample_count(foreign_thread_sample_count),
19 vm->record_callstack_sample(&callstack_begin, &callstack_end);
22 void factor_vm::record_sample()
24 cell recorded_sample_count;
25 cell recorded_gc_sample_count;
26 cell recorded_foreign_sample_count;
27 cell recorded_foreign_thread_sample_count;
29 FACTOR_MEMORY_BARRIER();
30 recorded_sample_count = safepoint_sample_count;
31 recorded_gc_sample_count = safepoint_gc_sample_count;
32 recorded_foreign_sample_count = safepoint_foreign_sample_count;
33 recorded_foreign_thread_sample_count = safepoint_foreign_thread_sample_count;
34 if (recorded_sample_count
35 + recorded_gc_sample_count
36 + recorded_foreign_sample_count
37 + recorded_foreign_thread_sample_count
41 /* Another sample signal could be raised while we record these counts */
42 FACTOR_ATOMIC_SUB(&safepoint_sample_count, recorded_sample_count);
43 FACTOR_ATOMIC_SUB(&safepoint_gc_sample_count, recorded_gc_sample_count);
44 FACTOR_ATOMIC_SUB(&safepoint_foreign_sample_count, recorded_foreign_sample_count);
45 FACTOR_ATOMIC_SUB(&safepoint_foreign_thread_sample_count, recorded_foreign_thread_sample_count);
47 samples.push_back(profiling_sample(
49 recorded_sample_count,
50 recorded_gc_sample_count,
51 recorded_foreign_sample_count,
52 recorded_foreign_thread_sample_count,
57 void factor_vm::record_callstack_sample(cell *begin, cell *end)
59 *begin = sample_callstacks.size();
60 stack_frame *frame = ctx->bottom_frame();
62 while (frame >= ctx->callstack_top) {
63 sample_callstacks.push_back(frame_code(frame));
64 frame = frame_successor(frame);
67 *end = sample_callstacks.size();
70 void factor_vm::set_sampling_profiler(bool sampling_p)
72 if (sampling_p == sampling_profiler_p)
76 start_sampling_profiler();
78 end_sampling_profiler();
81 void factor_vm::clear_samples()
83 // Swapping into temporaries releases the vector's allocated storage,
84 // whereas clear() would leave the allocation as-is
85 std::vector<profiling_sample> sample_graveyard;
86 std::vector<code_block*> sample_callstack_graveyard;
87 samples.swap(sample_graveyard);
88 sample_callstacks.swap(sample_callstack_graveyard);
91 void factor_vm::start_sampling_profiler()
93 safepoint_sample_count = 0;
94 safepoint_gc_sample_count = 0;
96 samples.reserve(10*FACTOR_PROFILE_SAMPLES_PER_SECOND);
97 sample_callstacks.reserve(100*FACTOR_PROFILE_SAMPLES_PER_SECOND);
98 sampling_profiler_p = true;
99 start_sampling_profiler_timer();
102 void factor_vm::end_sampling_profiler()
104 sampling_profiler_p = false;
105 FACTOR_MEMORY_BARRIER();
106 end_sampling_profiler_timer();
110 void factor_vm::primitive_sampling_profiler()
112 set_sampling_profiler(to_boolean(ctx->pop()));
115 void factor_vm::primitive_get_samples()
117 if (sampling_profiler_p || samples.empty()) {
118 ctx->push(false_object);
120 data_root<array> samples_array(allot_array(samples.size(), false_object),this);
121 std::vector<profiling_sample>::const_iterator from_iter = samples.begin();
124 for (; from_iter != samples.end(); ++from_iter, ++to_i)
126 data_root<array> sample(allot_array(6, false_object),this);
128 set_array_nth(sample.untagged(),0,from_unsigned_cell(from_iter->sample_count));
129 set_array_nth(sample.untagged(),1,from_unsigned_cell(from_iter->gc_sample_count));
130 set_array_nth(sample.untagged(),2,from_unsigned_cell(from_iter->foreign_sample_count));
131 set_array_nth(sample.untagged(),3,from_unsigned_cell(from_iter->foreign_thread_sample_count));
132 set_array_nth(sample.untagged(),4,allot_alien((void*)from_iter->ctx));
134 cell callstack_size = from_iter->callstack_end - from_iter->callstack_begin;
135 data_root<array> callstack(allot_array(callstack_size,false_object),this);
137 std::vector<code_block*>::const_iterator
138 callstacks_begin = sample_callstacks.begin(),
139 c_from_iter = callstacks_begin + from_iter->callstack_begin,
140 c_from_iter_end = callstacks_begin + from_iter->callstack_end;
143 for (; c_from_iter != c_from_iter_end; ++c_from_iter, ++c_to_i)
144 set_array_nth(callstack.untagged(),c_to_i,(*c_from_iter)->owner);
146 set_array_nth(sample.untagged(),5,callstack.value());
148 set_array_nth(samples_array.untagged(),to_i,sample.value());
150 ctx->push(samples_array.value());
154 void factor_vm::primitive_clear_samples()