sidekick/src/util/Profile.ml
2022-07-14 22:09:13 -04:00

93 lines
2 KiB
OCaml

module type BACKEND = sig
val get_ts : unit -> float
val emit_duration_event :
name:string -> start:float -> end_:float -> unit -> unit
val emit_instant_event : name:string -> ts:float -> unit -> unit
val teardown : unit -> unit
end
type backend = (module BACKEND)
type probe = No_probe | Probe of { name: string; start: float }
let null_probe = No_probe
(* where to print events *)
let out_ : backend option ref = ref None
let[@inline] enabled () =
match !out_ with
| Some _ -> true
| None -> false
let[@inline never] begin_with_ (module B : BACKEND) name : probe =
Probe { name; start = B.get_ts () }
let[@inline] begin_ name : probe =
match !out_ with
| None -> No_probe
| Some b -> begin_with_ b name
let[@inline] instant name =
match !out_ with
| None -> ()
| Some (module B) ->
let now = B.get_ts () in
B.emit_instant_event ~name ~ts:now ()
(* slow path *)
let[@inline never] exit_full_ (module B : BACKEND) name start =
let now = B.get_ts () in
B.emit_duration_event ~name ~start ~end_:now ()
let[@inline] exit_with_ b pb =
match pb with
| No_probe -> ()
| Probe { name; start } -> exit_full_ b name start
let[@inline] exit pb =
match pb, !out_ with
| Probe { name; start }, Some b -> exit_full_ b name start
| _ -> ()
let[@inline] with_ name f =
match !out_ with
| None -> f ()
| Some b ->
let pb = begin_with_ b name in
(try
let x = f () in
exit_with_ b pb;
x
with e ->
exit_with_ b pb;
raise e)
let[@inline] with1 name f x =
match !out_ with
| None -> f x
| Some b ->
let pb = begin_with_ b name in
(try
let res = f x in
exit_with_ b pb;
res
with e ->
exit_with_ b pb;
raise e)
let[@inline] with2 name f x y = with_ name (fun () -> f x y)
module Control = struct
let setup b =
assert (!out_ = None);
out_ := b
let teardown () =
match !out_ with
| None -> ()
| Some (module B) ->
out_ := None;
B.teardown ()
end