! (c)2011 Joe Groff bsd license
USING: accessors assocs calendar combinators
-combinators.short-circuit continuations fry io kernel
-kernel.private locals math math.statistics math.vectors memory
-namespaces prettyprint sequences sets sorting
-tools.profiler.sampling.private hashtables.identity generalizations ;
+combinators.short-circuit continuations fry generalizations
+hashtables.identity io kernel kernel.private locals math
+math.statistics math.vectors memory namespaces prettyprint
+sequences sequences.generalizations sets sorting
+tools.profiler.sampling.private ;
FROM: sequences => change-nth ;
FROM: assocs => change-at ;
IN: tools.profiler.sampling
[ 0 profiling ] [ ] cleanup
(get-samples) raw-profile-data set-global ; inline
-: total-sample-count ( sample -- count ) first ;
-: gc-sample-count ( sample -- count ) second ;
-: foreign-sample-count ( sample -- count ) third ;
-: foreign-thread-sample-count ( sample -- count ) fourth ;
-: sample-thread ( sample -- alien ) 4 swap nth ;
-: sample-callstack ( sample -- array ) 5 swap nth ;
+: total-sample-count ( sample -- count ) 0 swap nth ;
+: gc-sample-count ( sample -- count ) 1 swap nth ;
+: jit-sample-count ( sample -- count ) 2 swap nth ;
+: foreign-sample-count ( sample -- count ) 3 swap nth ;
+: foreign-thread-sample-count ( sample -- count ) 4 swap nth ;
+: sample-counts-slice ( sample -- counts ) 5 head-slice ;
+
+: sample-thread ( sample -- alien ) 5 swap nth ;
+: sample-callstack ( sample -- array ) 6 swap nth ;
+: unclip-callstack ( sample -- sample' callstack-top )
+ clone 6 over [ unclip swap ] change-nth ;
: samples>time ( samples -- time )
samples-per-second get-global / seconds ;
: time-per-thread ( -- n )
get-raw-profile-data collect-threads [ (total-time) ] assoc-map ;
-: unclip-callstack ( sample -- sample' callstack-top )
- clone 5 over [ unclip swap ] change-nth ;
-
: leaf-callstack? ( callstack -- ? )
[ ignore-word? ] all? ;
-: sum-times ( samples -- times )
- { 0 0 0 0 } [ 4 head-slice v+ ] reduce ;
+CONSTANT: zero-counts { 0 0 0 0 0 }
+
+: sum-counts ( samples -- times )
+ zero-counts [ sample-counts-slice v+ ] reduce ;
TUPLE: profile-node
- total-time gc-time foreign-time foreign-thread-time children ;
+ total-time gc-time jit-time foreign-time foreign-thread-time children ;
: <profile-node> ( times children -- node )
- [ first4 [ samples>time ] 4 napply ] dip profile-node boa ;
+ [ 5 firstn [ samples>time ] 5 napply ] dip profile-node boa ;
: <profile-root-node> ( samples collector-quot -- node )
- [ sum-times ] swap bi <profile-node> ; inline
+ [ sum-counts ] swap bi <profile-node> ; inline
:: (collect-subtrees) ( samples child-quot -- children )
samples [ sample-callstack leaf-callstack? not ] filter
: collect-tops ( samples -- node )
[ unclip-callstack ] collect-pairs [
- [ sum-times ]
+ [ sum-counts ]
[ [ collect-tops ] (collect-subtrees) ] bi <profile-node>
] assoc-map ;
IH{ } clone :> per-word-samples
samples [| sample |
sample sample-callstack unique keys [ ignore-word? not ] filter [
- per-word-samples [ { 0 0 0 0 } or sample 4 head-slice v+ ] change-at
+ per-word-samples [ zero-counts or sample sample-counts-slice v+ ] change-at
] each
] each
per-word-samples [ f <profile-node> ] assoc-map ;
>alist [ second total-time>> ] inv-sort-with ;
: duration. ( duration -- )
- duration>milliseconds >integer pprint "ms" write ;
+ samples-per-second get-global {
+ { [ dup 1000 <= ] [ drop duration>milliseconds >integer pprint "ms" write ] }
+ { [ dup 1,000,000 <= ] [ drop duration>microseconds >integer pprint "µs" write ] }
+ [ drop duration>nanoseconds >integer pprint "ns" write ]
+ } cond ;
DEFER: (profile.)
: times. ( node -- )
{
- [ total-time>> duration. " (" write ]
- [ gc-time>> duration. " gc, " write ]
- [ foreign-time>> duration. " foreign, " write ]
- [ foreign-thread-time>> duration. " foreign threads)" write ]
+ [ total-time>> duration. ]
+ [ " (GC:" write gc-time>> duration. ]
+ [ ", JIT:" write jit-time>> duration. ]
+ [ ", FFI:" write foreign-time>> duration. ]
+ [ ", FT:" write foreign-thread-time>> duration. ")" write ]
} cleave ;
:: (profile-node.) ( word node depth -- )
position(0),
offset(0),
parent(vm)
-{}
+{
+ fixnum count = atomic::add(&parent->current_jit_count, 1);
+ assert(count >= 1);
+}
+
+jit::~jit()
+{
+ fixnum count = atomic::subtract(&parent->current_jit_count, 1);
+ assert(count >= 0);
+}
void jit::emit_relocation(cell relocation_template_)
{
factor_vm *parent;
explicit jit(code_block_type type, cell owner, factor_vm *parent);
+ ~jit();
+
void compute_position(cell offset);
void emit_relocation(cell relocation_template);
code_block *to_code_block();
+
+private:
+ jit(const jit&);
+ void operator=(const jit&);
};
}
profiling_sample_count returned(
sample_count,
gc_sample_count,
+ jit_sample_count,
foreign_sample_count,
foreign_thread_sample_count);
atomic::subtract(&sample_count, returned.sample_count);
atomic::subtract(&gc_sample_count, returned.gc_sample_count);
+ atomic::subtract(&jit_sample_count, returned.jit_sample_count);
atomic::subtract(&foreign_sample_count, returned.foreign_sample_count);
atomic::subtract(&foreign_thread_sample_count, returned.foreign_thread_sample_count);
return returned;
{
sample_count = 0;
gc_sample_count = 0;
+ jit_sample_count = 0;
foreign_sample_count = 0;
foreign_thread_sample_count = 0;
atomic::fence();
for (; from_iter != samples.end(); ++from_iter, ++to_i)
{
- data_root<array> sample(allot_array(6, false_object),this);
+ data_root<array> sample(allot_array(7, false_object),this);
set_array_nth(sample.untagged(),0,tag_fixnum(from_iter->counts.sample_count));
set_array_nth(sample.untagged(),1,tag_fixnum(from_iter->counts.gc_sample_count));
- set_array_nth(sample.untagged(),2,tag_fixnum(from_iter->counts.foreign_sample_count));
- set_array_nth(sample.untagged(),3,tag_fixnum(from_iter->counts.foreign_thread_sample_count));
+ set_array_nth(sample.untagged(),2,tag_fixnum(from_iter->counts.jit_sample_count));
+ set_array_nth(sample.untagged(),3,tag_fixnum(from_iter->counts.foreign_sample_count));
+ set_array_nth(sample.untagged(),4,tag_fixnum(from_iter->counts.foreign_thread_sample_count));
- set_array_nth(sample.untagged(),4,from_iter->thread);
+ set_array_nth(sample.untagged(),5,from_iter->thread);
cell callstack_size = from_iter->callstack_end - from_iter->callstack_begin;
data_root<array> callstack(allot_array(callstack_size,false_object),this);
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);
- set_array_nth(sample.untagged(),5,callstack.value());
+ set_array_nth(sample.untagged(),6,callstack.value());
set_array_nth(samples_array.untagged(),to_i,sample.value());
}
else {
if (atomic::load(¤t_gc_p))
atomic::add(&safepoint_sample_counts.gc_sample_count, samples);
+ if (atomic::load(¤t_jit_count) > 0)
+ atomic::add(&safepoint_sample_counts.jit_sample_count, samples);
if (pc != 0 && !code->seg->in_segment_p(pc))
atomic::add(&safepoint_sample_counts.foreign_sample_count, samples);
}
fixnum sample_count;
// Number of samples taken during GC
fixnum gc_sample_count;
+ // Number of samples taken during unoptimized compiler
+ fixnum jit_sample_count;
// Number of samples taken during foreign code execution
fixnum foreign_sample_count;
// Number of samples taken during code execution in non-Factor threads
profiling_sample_count() :
sample_count(0),
gc_sample_count(0),
+ jit_sample_count(0),
foreign_sample_count(0),
foreign_thread_sample_count(0) {}
profiling_sample_count(fixnum sample_count,
fixnum gc_sample_count,
+ fixnum jit_sample_count,
fixnum foreign_sample_count,
fixnum foreign_thread_sample_count) :
sample_count(sample_count),
gc_sample_count(gc_sample_count),
+ jit_sample_count(jit_sample_count),
foreign_sample_count(foreign_sample_count),
foreign_thread_sample_count(foreign_thread_sample_count) {}
{
return sample_count
+ gc_sample_count
+ + jit_sample_count
+ foreign_sample_count
+ foreign_thread_sample_count == 0;
}
gc_off(false),
current_gc(NULL),
current_gc_p(false),
- current_jit_p(false),
+ current_jit_count(0),
gc_events(NULL),
fep_p(false),
fep_help_was_shown(false),
volatile cell current_gc_p;
/* Set if we're in the jit */
- volatile cell current_jit_p;
+ volatile fixnum current_jit_count;
/* Mark stack */
std::vector<cell> mark_stack;