Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file online.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641openCoreopenPolyopenCore_profiler_disabledletdebug=falsetyperow=|Count_onlyofint|StatsofFstats.tletrow_stats=function|Count_only_->None|Statsst->Somestletrow_is_empty=function|Count_onlyn->n=0|Statsst->Fstats.samplesst=0letall_rows:((unit->row)*Profiler_units.t)String.Map.tref=refString.Map.emptyletcolumns=letfstats_count(_name,_units,row)=letcount=matchrowwith|Count_onlyn->n|Statsst->Fstats.samplesstinProfiler_units.format_intProfiler_units.Intcountinletfstats_fgetgetter(_name,units,row)=letopenOption.Monad_infixinrow_statsrow>>|getter>>=Float.iround_nearest>>|Profiler_units.format_intunits|>Option.value~default:""inAscii_table.([Column.create~align:Left"name"fst3;Column.create~align:Right"count"fstats_count;Column.create~align:Right"sum"(fstats_fgetFstats.total);Column.create~align:Right"mean"(fstats_fgetFstats.mean);Column.create~align:Right"min"(fstats_fgetFstats.min);Column.create~align:Right"max"(fstats_fgetFstats.max);Column.create~align:Right"stdev"(fstats_fgetFstats.stdev)])(* If we ever create an online probe we expect this will be set. *)letwe_are_using_online_profiler=reffalseletonline_profiler_is_used()=we_are_using_online_profiler:=true(* Used for benchmarks, tests etc where we don't what the online outputs, we can disable
the printing by setting this. *)letinternal_disable_print=reffalse(* Printing configuration supplied by the user. *)letprint_enabled=letenv="PRINT_ENABLED"inletv=matchCheck_environment.get_varenvwith|Some"true"->true|Some"false"->false|Somev->Core.printf"Unknown value for %s for %s, use true or false\n%!"venv;true|None->trueinrefv(* Printing configuration supplied by the user. *)letprint_interval=letenv="PRINT_INTERVAL"inletv=matchCheck_environment.get_varenvwith|Somev->Int.of_stringv|None->1inrefvletonline_print()=ifnot!internal_disable_print&&!we_are_using_online_profilerthenbeginCore.printf!"%{Time}\n%!"(Time.now());lettable=Map.fold_right!all_rows~init:[]~f:(fun~key:name~data:(row_fn,units)acc->letrow=row_fn()inifrow_is_emptyrowthenaccelse(name,units,row)::acc)inifnot(List.is_emptytable)thenbeginAscii_table.output~oc:Out_channel.stdout~limit_width_to:150columnstable;Out_channel.flushOut_channel.stdoutendendletmaybe_print=letlast_print=ref(Common.now_no_calibrate())infun()->if!print_enabledthenbeginletnow=Common.now_no_calibrate()inletdiff=Time_ns.diffnow!last_print|>Time_ns.Span.to_int_secinifdebugthenCore.printf"print_interval = %d, diff = %d\n"!print_intervaldiff;ifdiff>=!print_intervalthenbeginlast_print:=now;online_print()endendletadd_print_to_slow_tasks=letonce=reffalseinfun()->ifnot!oncethenbeginCommon.add_slow_taskCommon.Online_profilermaybe_print;once:=trueendlet()=at_exitonline_printletadd_row:string->(unit->row)->Profiler_units.t->unit=add_print_to_slow_tasks();funnamefnunits->all_rows:=Map.set!all_rows~key:name~data:(fn,units)letsafe_to_delay()=Common.maybe_do_slow_tasksCommon.Online_profiler~reluctance:1moduleProfiler=structletis_enabled=trueletsafe_to_delay=safe_to_delayletdump_stats=online_printletconfigure?don't_require_core_profiler_env?offline_profiler_data_file:_?online_print_time_interval_secs?online_print_by_default()=Option.iterdon't_require_core_profiler_env~f:(fun()->Check_environment.don't_require_core_profiler_env());Option.iteronline_print_by_default~f:(funbool->print_enabled:=bool);Option.iteronline_print_time_interval_secs~f:(funsecs->print_interval:=secs);;endmoduleTimer=structmoduleSingle=structtypet={name:string;mutablecount:int}letcreatename()=online_profiler_is_used();Check_environment.check_safety_exn();lett={name;count=0}inadd_rowname(fun()->Count_onlyt.count)Profiler_units.Int;tletrecordt=t.count<-t.count+1;Common.maybe_do_slow_tasksCommon.Online_profiler~reluctance:3endmoduleRaw_group=structtypet={name:string(* [session] is initialised to 0 *);mutablesession:int}letcreate~name=online_profiler_is_used();{name;session=0}letresetgroup=Common.maybe_do_slow_tasksCommon.Online_profiler~reluctance:2;group.session<-group.session+1endmoduleGroup_probe=structtypet={name:string;group:Raw_group.t;sources:(t*Fstats.t)array(* [session] is initialised to -1 *);mutablesession:int(* [last_time] is initalised to the epoch; the value won't be used since session
won't match *);mutablelast_time:Time_ns.t}letrecordt=letn=Common.nowCommon.Online_profiler~reluctance:4()inletgsession=t.group.sessioninfori=0to(Array.lengtht.sources-1)dolet(src,stats)=t.sources.(i)inifsrc.session=gsessionthenTime_ns.diffnsrc.last_time|>Time_ns.Span.to_int_ns|>float|>Fstats.update_in_placestatsdone;t.last_time<-n;t.session<-gsessionletcreategroup~sources~name=online_profiler_is_used();Check_environment.check_safety_exn();letprobe={name;group;sources=Array.mapsources~f:(funsrc->(src,Fstats.create()));last_time=Time_ns.epoch;session=-1}inArray.iterprobe.sources~f:(fun(src,stats)->letrow_name=group.name^":"^src.name^","^nameinadd_rowrow_name(fun()->Stats(Fstats.copystats))Profiler_units.Nanoseconds);probeendtypet=|SingleofSingle.t|Group_probeofGroup_probe.ttypeprobe=tletcreate~name=Single(Single.createname())letrecord=function|Singlet->Single.recordt|Group_probet->Group_probe.recordtmoduleGroup=structincludeRaw_groupletadd_probet?(sources=[||])~name()=letsources=Array.mapsources~f:(fun(src:probe)->matchsrcwith|Single_->failwith"Probe sources must come from the same group"|Group_probesrc->ifsrc.group<>tthenfailwith"Probe sources must come from the same group"elsesrc);inGroup_probe(Group_probe.createt~sources~name)endendlet%bench_module"Timer"=(modulestructlettimer=Timer.create~name:"bench_timer"letgroup=Timer.Group.create~name:"bench_timer_group"letgroup_probe0=Timer.Group.add_probegroup~name:"bench_timer_group_probe0"()letgroup_probe1=Timer.Group.add_probegroup~name:"bench_timer_group_probe1"()~sources:[|group_probe0|]letgroup_probe2=Timer.Group.add_probegroup~name:"bench_timer_group_probe2"()~sources:[|group_probe0;group_probe1|]let()=Timer.recordgroup_probe0;Timer.recordgroup_probe1;Timer.recordgroup_probe2let%bench"at"=Timer.recordtimerlet%bench"group_probe_at (0 sources)"=Timer.recordgroup_probe0let%bench"group_probe_at (1 sources)"=Timer.recordgroup_probe1let%bench"group_probe_at (2 sources)"=Timer.recordgroup_probe2letgroup2=Timer.Group.create~name:"bench_timer_group2"let%bench"group_reset"=Timer.Group.resetgroup2let()=internal_disable_print:=trueend)moduleProbe=struct(* A probe doesn't need to know its name, so we can save an indirection. *)moduleSingle=structtypet=Fstats.tletcreatenameunits=online_profiler_is_used();Check_environment.check_safety_exn();lett=Fstats.create()inadd_rowname(fun()->Stats(Fstats.copyt))units;tletrecordtvalue=Fstats.update_in_placet(floatvalue);Common.maybe_do_slow_tasksCommon.Online_profiler~reluctance:3endmoduleRaw_group=structtypet={name:string;units:Profiler_units.t(* [session] is initialised to 0 *);mutablesession:int}letcreate~name~units=online_profiler_is_used();{name;units;session=0}letresetgroup=Common.maybe_do_slow_tasksCommon.Online_profiler~reluctance:2;group.session<-group.session+1endmoduleGroup_probe=structtypet={name:string;group:Raw_group.t;sources:(t*Fstats.t)array(* See [Timer.Group.Probe.t] *);mutablesession:int;mutablelast_value:int}letcreategroup~sources~name=online_profiler_is_used();Check_environment.check_safety_exn();letprobe={name;group;sources=Array.mapsources~f:(funsrc->(src,Fstats.create()));last_value=0;session=-1}inArray.iterprobe.sources~f:(fun(src,stats)->letrow_name=group.name^":"^src.name^","^nameinadd_rowrow_name(fun()->Stats(Fstats.copystats))group.units);probeletrecordtvalue=letgsession=t.group.sessionin(* Using Array.iter would cause allocation of a closure *)fori=0to(Array.lengtht.sources-1)dolet(src,stats)=t.sources.(i)inifsrc.session=gsessionthenFstats.update_in_placestats(float(value-src.last_value))done;t.last_value<-value;t.session<-gsession;Common.maybe_do_slow_tasksCommon.Online_profiler~reluctance:4endtypet=|SingleofSingle.t|Group_probeofGroup_probe.ttypeprobe=tletcreate~name~units=Single(Single.createnameunits)letrecordtvalue=matchtwith|Singlet->Single.recordtvalue|Group_probet->Group_probe.recordtvaluemoduleGroup=structincludeRaw_groupletadd_probet?(sources=[||])~name()=letsources=Array.mapsources~f:(fun(src:probe)->matchsrcwith|Single_->failwith"Probe sources must come from the same group"|Group_probesrc->ifsrc.group<>tthenfailwith"Probe sources must come from the same group"elsesrc)inGroup_probe(Group_probe.createt~sources~name)endendlet%bench_module"Probe"=(modulestructletprobe=Probe.create~name:"bench_probe"~units:Profiler_units.Secondsletgroup=Probe.Group.create~name:"bench_probe_group"~units:Profiler_units.Wordsletgroup_probe0=Probe.Group.add_probegroup~name:"bench_probe_group_probe0"()letgroup_probe1=Probe.Group.add_probegroup~name:"bench_probe_group_probe1"~sources:[|group_probe0|]()letgroup_probe2=Probe.Group.add_probegroup~name:"bench_probe_group_probe2"~sources:[|group_probe0;group_probe1|]()let()=Probe.recordgroup_probe02;Probe.recordgroup_probe13;Probe.recordgroup_probe24let%bench"at"=Probe.recordprobe10let%bench"group_probe_at (0 sources)"=Probe.recordgroup_probe05let%bench"group_probe_at (1 sources)"=Probe.recordgroup_probe16let%bench"group_probe_at (2 sources)"=Probe.recordgroup_probe27letgroup2=Probe.Group.create~name:"bench_probe_group2"~units:Profiler_units.Intlet%bench"group_reset"=Probe.Group.resetgroup2let()=internal_disable_print:=trueend)(* stateless Delta_timer does not support pausing *)moduleDelta_timer=structtypestate=Time_ns.ttypet={name:string;stats:Fstats.t;mutablestate:state;mutableaccum:int}letcreate~name=lett={name;stats=Fstats.create();state=Time_ns.epoch;accum=0}inonline_profiler_is_used();add_rowname(fun()->Stats(Fstats.copyt.stats))Profiler_units.Nanoseconds;tletdiffnstate=Time_ns.diffnstate|>Time_ns.Span.to_int_nsletupdate_in_placetd=Fstats.update_in_placet.stats(floatd)letupdate_in_place_and_reset_accumtd=update_in_placetd;t.accum<-0letstateless_start_=Common.nowCommon.Online_profiler~reluctance:4()letstateless_stoptstate=letn=Common.nowCommon.Online_profiler~reluctance:4()inletd=diffnstateinupdate_in_placetdletstartt=t.state<-Common.nowCommon.Online_profiler~reluctance:4()letpauset=letn=Common.nowCommon.Online_profiler~reluctance:4()int.accum<-t.accum+(diffnt.state)letrecordt=update_in_place_and_reset_accumtt.accum;Common.maybe_do_slow_tasksCommon.Online_profiler~reluctance:2letstopt=pauset;update_in_place_and_reset_accumtt.accumletwrap_synctfx=letstate=stateless_starttinletr=tryfxwithex->stateless_stoptstate;Exn.reraiseex"Core_profiler Delta_timer.wrap_sync"instateless_stoptstate;rletwrap_sync2tfxy=letstate=stateless_starttinletr=tryfxywithex->stateless_stoptstate;Exn.reraiseex"Core_profiler Delta_timer.wrap_sync2"instateless_stoptstate;rletwrap_sync3tfxyz=letstate=stateless_starttinletr=tryfxyzwithex->stateless_stoptstate;Exn.reraiseex"Core_profiler Delta_timer.wrap_sync3"instateless_stoptstate;rletwrap_sync4tfxyzw=letstate=stateless_starttinletr=tryfxyzwwithex->stateless_stoptstate;Exn.reraiseex"Core_profiler Delta_timer.wrap_sync4"instateless_stoptstate;r(* let wrap_async t f x =
* let open Async in
* let state = start_async t in
* try_with ~run:`Now (fun () -> f x) >>= fun res ->
* stop_async t state;
* match res with
* | Ok x -> return x
* | Error ex -> Exn.reraise ex "Core_profiler Delta_timer.wrap_async" *)endlet%bench_module"Delta_timer"=(modulestructletdelta=Delta_timer.create~name:"unittest"letstarted=Delta_timer.stateless_startdeltalet%bench"stateless_start"=Delta_timer.stateless_startdeltalet%bench"stateless_stop"=Delta_timer.stateless_stopdeltastartedlet%bench"start"=Delta_timer.startdeltalet%bench"stop"=Delta_timer.stopdeltalet()=internal_disable_print:=trueend)let%bench_module"Delta_timer.wrap_sync"=(modulestructletnop()=()letwrapped_nop=letdelta=Delta_timer.create~name:"nop"inDelta_timer.wrap_syncdeltanopletcount_256()=for_=1to256do()doneletwrapped_count_256=letdelta=Delta_timer.create~name:"count_256"inDelta_timer.wrap_syncdeltacount_256let%bench"nop"=nop()let%bench"wrapped_nop"=wrapped_nop()let%bench"count_256"=count_256()let%bench"wrapped_count_256"=wrapped_count_256()let()=internal_disable_print:=trueend)(* stateless Delta_probe does not support pausing *)moduleDelta_probe=structtypestate=inttypet={name:string;stats:Fstats.t;mutablestate:state;mutableaccum:state}letcreate~name~units=lett={name;stats=Fstats.create();state=0;accum=0}inonline_profiler_is_used();add_rowname(fun()->Stats(Fstats.copyt.stats))units;tletstateless_start_value=valueletstateless_stoptstatevalue=Fstats.update_in_placet.stats(float(value-state));Common.maybe_do_slow_tasksCommon.Online_profiler~reluctance:3letstarttvalue=t.state<-valueletpausetvalue=t.accum<-t.accum+value-t.stateletrecordt=Fstats.update_in_placet.stats(floatt.accum);t.accum<-0;Common.maybe_do_slow_tasksCommon.Online_profiler~reluctance:3letstoptvalue=pausetvalue;recordtendlet%bench_module"Delta_probe"=(modulestructletdelta=Delta_probe.create~name:"unittest"~units:Profiler_units.Intletstarted=Delta_probe.stateless_startdelta123let%bench"start"=Delta_probe.startdelta123let%bench"stop"=Delta_probe.stopdelta456let%bench"start_async"=Delta_probe.stateless_startdelta123let%bench"stop_async"=Delta_probe.stateless_stopdeltastarted456let()=internal_disable_print:=trueend)