Module Profiler_intf.Delta_probe

Delta_probe is an optimized two-probe group to track changes to some counter.

type t
type state
val create : name:string -> units:Profiler_units.t -> t
val start : t -> int -> unit

To measure changes in a value, one can call start followed by a call stop after some time. The call to stop will record the delta. Calls to start/stop must be interleaved for each t.

Calling pause in place of stop causes t to accumulate, but not record, the delta. start and pause can then be interleaved multiple times. Afterwards, calling record will record the sum of the deltas between each start/pause, and reset t.

Valid sequences should satisfy this regular expression:


Calling these functions out of order will cause bad data to be recorded. This API does not raise exceptions, so one will not be warned of errors.

For each t, there are two valid sequences of calls. The first is calling start then stop. The second is calling start then pause an arbitrary number of times, and ending with record.

val stop : t -> int -> unit
val pause : t -> int -> unit
val record : t -> unit
val stateless_start : t -> int -> state

These are non-stateful and can be used in Async, wherein multiple jobs might call stateless_start before the corresponding stop_async is called. One can use stateless_start and stateless_stop to wrap async functions roughly like the following. This function cannot be provided as part of the Core_profiler library because we'd like the library to be usable in Async and hence now depend on it.

let wrap_async t f x =
  let state = stateless_start t (Gc.minor_words ()) in
  try_with ~run:`Now (fun () -> f x)
  >>= fun res ->
  stateless_stop t state (Gc.minor_words ());
  match res with
  | Ok x -> return x
  | Error ex -> Exn.reraise ex "Core_profiler wrap_async"

The stateless API does not support pausing. This is because state would require memory allocation if it supported accumulating the counter.

val stateless_stop : t -> state -> int -> unit