sidekick/src/util/Profile.ml
2021-06-11 21:53:13 -04:00

107 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