pub struct WalkAttribution {
pub wall_ns: u64,
pub work_ns: u64,
pub starved_ns: u64,
pub lock_wait_ns: u64,
pub send_ns: u64,
pub claims: u64,
pub lock_ops: u64,
pub lock_contended: u64,
}Expand description
Where a walk’s time went, so “blocked” is never one undifferentiated number.
The performance loop’s standing question is whether a walk is bound by disk I/O, by CPU, or by coordination, and process-level counters cannot answer it: user and system time say how much CPU was burned, but a fused “blocked” number cannot say whether workers were waiting on the filesystem, on the queue lock, or on nothing at all because the queue was empty. These counters split that out at the source.
Everything is measured in chunks, never per file: one timing pair per claimed
run of directories, per contended lock, per batch handoff. On the 60k-entry
reference tree that is a few thousand Instant reads against hundreds of
milliseconds of walking — the instrumentation follows the same amortization rule
it exists to verify.
In a parallel walk the fields sum over workers, so wall_ns is worker-seconds
(it can exceed the scan’s wall clock) and every other duration is a disjoint
slice of it: work_ns + starved_ns + lock_wait_ns + send_ns <= wall_ns, with the
remainder being uninstrumented odds and ends (uncontended lock ops, loop
bookkeeping). A serial walk fills only wall_ns, work_ns, and send_ns —
there is no coordination to attribute.
Fields§
§wall_ns: u64Total time workers spent in the walk loop, summed across workers.
work_ns: u64Reading directories and stating entries — the real work, syscalls plus the compute between them. Separating disk from CPU within this span needs the process-level user/system counters alongside; per-syscall timing would break the chunk-amortization rule.
starved_ns: u64Waiting on the queue’s condvar because no work was available. Starvation: either the frontier is momentarily narrower than the worker pool, or the walk is ending.
lock_wait_ns: u64Waiting to acquire the queue lock when another worker held it. This is the contention the shared-queue design bets stays negligible; now it is measured instead of argued.
send_ns: u64Handing observation batches to the consumer: the channel send in a parallel walk, the inline sink call — which is the consumer actually running — in a serial one.
claims: u64Chunks of directories claimed from the queue.
lock_ops: u64Queue lock acquisitions, contended or not.
lock_contended: u64Lock acquisitions that found the lock already held.
Implementations§
Source§impl WalkAttribution
impl WalkAttribution
Sourcepub fn accounted_ns(&self) -> u64
pub fn accounted_ns(&self) -> u64
Time attributed to a named cause, as opposed to wall_ns’s total.