Module Rig.Profile
Profiles of devices' work.
A profile of every device is taken while a function runs (Profile.take). Profiles nest and overlap, in any domains, and each holds the events recorded while it is taken. Every time is on the host clock (Profile.now). When no profile is being taken, recording costs one atomic read and allocates nothing. Taking a profile may slow the submits of a device whose driver times its work, as the driver's interface states.
type event = - #
| Work of {- #
point : Point.t; - #
device : device; - #
lane : string;(*Its track within the device.
*) - #
name : string; - #
start : int; - #
stop : int;
}(*A submission's work on a lane of its device, from when the device started it to when the device ended all its parts' work, on the lane of the queue its first part ran on, such as
"COMPUTE:0"(Rig_edge.queue). Each submission with parts records it. It is named after the functions its launches run, in the order of its parts, joined by", ", or, with no launch, after its first part's kind,"copies","fills"or"words". A device whose driver cannot time a submission's work records none of it, nor does one whose driver finds the work's converted times outside the host's window around it, from the submit to their conversion, by more than the driver states.Its driver converts the device's clock to the host's through measures of one against the other. A time's error is the deviation of the measures it was converted with, as each driver states, plus the error of extrapolating since the latest.
*) - #
- #
| Span of {- #
device : device; - #
lane : string;(*Its track within the device.
*) - #
name : string; - #
start : int; - #
stop : int;
} - #
- #
| Allocation of {}(*The bytes of memory
*)deviceallocated fromtimeon. - #
| Load of {}(*An image loaded.
*) - #
| Counters of {- #
device : device; - #
name : string; - #
start : int; - #
stop : int; - #
counters : (string * int array) list;(*Each counter's name and its count during the run, one per unit of the hardware that counts it.
*)
}(*The counters of a run of a function.
*) - #
- #
| Trace of {- #
device : device; - #
name : string; - #
start : int; - #
stop : int; - #
part : int;(*The index of the device's unit that wrote it.
*) - #
data : string;(*The trace as the device wrote it.
*)
}(*The thread trace that a unit of a device wrote during a run.
*) - #
- #
| Unmeasured of {}(*
*)runsruns of functions ondevice, submitted while a profile was taken, whose counters its driver could not measure, as the driver's interface states.timeis the end of their submission's work, or when rig read them where the device could not time that work. - #
| Copy of {- #
src : device; - #
dst : device; - #
bytes : int; - #
point : Point.t option;(*
*)Some pfor a copy a device runs,pits submission's point, andNonefor a copy the host or an io device runs. - #
start : int; - #
stop : int;
}(*A transfer of
bytesfromsrc's memory todst's: a copy part of a submission (Submission.copy), rig's own and those of aBuffer.submit_copyamong them, or a copy the host or an io device runs. A box (Buffer.box) records the bytes of its rows.srcanddstare the devices in whoseallocatedcount the memory the bytes leave and reach lies (Reclamation), or the device whose memory it is where it counts in none. So aBuffer.borrownames the device whose memory it borrows, andPinnedmemory the device whose budget it counts in.Each copy part of a submission records an event with the times of the submission's
*)Workwhere its device times the work. Otherwise the event starts when the copy was asked, at the submit. It ends when the copy ended where the submit runs it, as for a copy the host, an io device or amemory_deviceruns, and otherwise whentakereads that it is done, so the event then lasts at least as long as the copy. A copy through staging memory records each piece into and out of it, withhostas one side, and no event of its own. A fill (Buffer.submit_fill) moves no bytes from memory and records none: where a device runs it, its submission'sWorkis named"copies". - #
The type for profile events. Times are nanoseconds of the host clock. rig records a submission's work, spans, allocations, loads and copies. A device whose driver measures its launches' counters records Counters and Unmeasured events, as its driver's interface states. A library whose compiled code measures its work, such as with a device's thread traces, records Trace events (record).
take f is f () and the events recorded while it ran, in time order and, at equal times, longest first, then in the order they were recorded. Before it returns it waits for the work whose events are still to be read, such as the submissions made while it ran. If f raises, take discards the events and raises the exception again with its backtrace.
Raises Lost naming a device whose events are still to be read if it is lost before they are read, having discarded the events. That device may be any whose work was recorded while f ran, another domain's included. A close first reads its device's events of completed work, so a device that f closes raises nothing. An event that another domain's take has begun to read when the close starts stays that take's, which then raises the close's Lost.
val enabled : unit -> boolenabled () is true iff some profile is being taken.
val now : unit -> intnow () is the host clock, in nanoseconds of the system's monotonic clock from an unspecified start.
record e adds e to each profile being taken when it is called, so take returns it among rig's own events, in time order. It records nothing while no profile is being taken, so counters a library reads after take has returned join no profile, even one of the work they count.
val span : string -> (unit -> 'a) -> 'aspan name f is f (), recorded as a span named name on the calling domain's lane of host, from the call until f returns or raises, in each profile taken when the call starts.
output_chrome_trace oc events writes events to oc in Chrome's trace event format, JSON, which Perfetto and chrome://tracing load. It writes a process per device, a thread per lane, a complete event per work and span, per copy (on its src's process) and per run's counters (each summed over its units), a counter memory per allocation change, and instant events for loads, traces and unmeasured runs. Times are microseconds from the earliest event. oc is neither flushed nor closed.