2.5. Analysis computes inclusive and self time
After the session closes, analyze first sorts the events by reservation index and validates their
structure. It checks duplicate indices, missing parents, impossible depths, reversed intervals, and
child intervals that extend outside their parents. Validation issues remain in the report instead
of being silently repaired into benchmark data.
For an event with interval I, inclusive time is simply the length of I. Self time removes
the portion covered by its immediate children on the same thread:
t_{\mathrm{self}}(e)
= |I_e| - \left|\bigcup_{c \in C_e} (I_c \cap I_e)\right|
The union is important. If malformed or overlapping child intervals cover the same nanoseconds, those nanoseconds are subtracted once, not once per child. Intervals are clipped to the parent, and subtraction is bounded so a diagnostic report cannot contain self time larger than inclusive time.
Cross-thread children are not subtracted. Two threads may run simultaneously, so removing a worker thread's elapsed interval from its caller would confuse a causal relationship with exclusive time on one clock. The parent link remains available in the trace for correlation.
Heartbeats follow the same parent rule when a same-thread child lies completely inside its parent. The analysis layer proves that every emitted timing has self time no greater than inclusive time, and likewise for heartbeats.