123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123(** {1 profiling facilities} *)typetimestamp=floatlet[@inline]timestamp_subab=a-.blet[@inline]timestamp_addab=a+.blet[@inline]timestamp_cmpab=CCFloat.compareab(** A profiler (do not call recursively) *)typet={prof_name:string;mutableprof_total:timestamp;(* total time *)mutableprof_calls:int;(* number of calls *)mutableprof_max:timestamp;(* max time in the profiled function (ns) *)mutableprof_enter:timestamp;(* time at which we entered the profiler (ns) *)}(* NOTE: profiling:
enables compile-time branch cutting.
if you want profiling, change this to [true]. *)let__prof=falseletactive_=reffalseletenable_profilingb=ifb&¬__profthen(Util.errorf~where:"zprof""profiling has been deactivated at compile time. \
Change `ZProf.__prof` and recompile.")letprofilers=ref[]letmakename=letprof={prof_name=name;prof_enter=0.;prof_total=0.;prof_calls=0;prof_max=0.;}in(* register profiler *)if__profthen(profilers:=prof::!profilers;);proflet[@inline]enter_profprofiler=if__prof&&!active_then(profiler.prof_enter<-Util.get_time_mon_())let[@inlinenever]exit_prof_profiler=letstop=Util.get_time_mon_()inletdelta=timestamp_substopprofiler.prof_enterinprofiler.prof_total<-timestamp_addprofiler.prof_totaldelta;profiler.prof_calls<-profiler.prof_calls+1;ifdelta>profiler.prof_maxthenprofiler.prof_max<-delta;()let[@inline]exit_profprofiler=if__prof&&!active_then(exit_prof_profiler)letwith_prof_pfx=enter_profp;trylety=fxinexit_profp;ywithe->exit_profp;raiseelet[@inline]with_profpfx=if__prof&&!active_then(with_prof_pfx)else(fx)letshow_profilersout()=Format.fprintfout"@[<v>";Format.fprintfout"@[%39s ---------- --------- --------- --------- ---------@]@,"(String.make39'-');Format.fprintfout"@[%-39s %10s %9s %9s %9s %9s@]@,""function""#calls""total""% total""max""average";(* sort profilers by decreasing total time *)letprofilers=List.sort(funp1p2->-(timestamp_cmpp1.prof_totalp2.prof_total))!profilersinlettot=Util.total_time_s()inList.iter(funprofiler->ifprofiler.prof_calls>0then(* print content of the profiler *)Format.fprintfout"@[%-39s %10d %9.4f %9.2f %9.4f %9.4f@]@,"profiler.prof_nameprofiler.prof_callsprofiler.prof_total(profiler.prof_total*.100./.tot)profiler.prof_max(profiler.prof_total/.(float_of_intprofiler.prof_calls)))profilers;Format.fprintfout"@]";()(** Print profiling data upon exit *)let()=if__profthen(Options.add_opts["--profile",Arg.Unit(fun()->enable_profilingtrue)," enable profiling probes";"--no-profile",Arg.Unit(fun()->enable_profilingfalse)," disable profiling probes";];at_exit(fun()->if!active_thenFormat.eprintf"%a@."show_profilers()))