/** * The `samples → slices` transform: turn raw JS Self-Profiling output (per-sample interned stacks) * into the nested timed-slice (call-tree) wire model the codec stores. This is the canonical view over * the profile model, so every consumer (transcode, analysis) slices identically. * * WHY slices: a sampling profiler can't measure durations; it can only observe that a frame was on the * stack across a run of consecutive samples. We coalesce each contiguous run into one slice and keep * only runs that span **at least ~1 sample interval** (`duration >= 0.8 × interval`; the 0.8 tolerates * cadence jitter, which CPU throttling pushes down to ~8ms — verified on the corpus). * Anything shorter is below the sampling resolution — a single sample, a duplicate-timestamp cluster, * or a microsecond-spaced burst (Chrome emits these as a deep recursion unwinds; on cross-origin- * isolated pages they even tie into identical 5µs-grid timestamps) — i.e. not a slow main-thread block. * This is a responsiveness view, not CPU-time accounting (see docs/Plan.md). The floor is the actual * sample interval, not a separate knob. Durations are sample-INFERRED (±1 interval), never measured. * * `SliceBuilder` is INCREMENTAL: feed it raw `Profiler.stop()` chunks via `addChunk()` and it folds * each into an accumulating call-tree — interning frames/resources across chunks and stitching a run * that continues across a checkpoint. That is the capture→wire seam: the on-page driver stops/restarts * the profiler at safe (idle) checkpoints and folds each batch, so the heavy work is spread across the * session and the unload path only flushes the small remainder (no unload serialization cliff). The * profiler delivers samples only in a batch at `stop()`, so chunking is the only way to be incremental. */ import type { ProfilerTrace, SliceProfile } from './streams/profile.js'; export interface SliceBuilderOptions { /** The actual (clamped) sample interval; stored on the result as the inference granularity. */ sampleIntervalMs?: number; } /** * Incremental folder from raw profiler trace chunks to one `SliceProfile`. Reusable across one capture * session: `addChunk()` per `Profiler.stop()`, then `finish()` once at the end. */ export declare class SliceBuilder { #private; constructor(opts?: SliceBuilderOptions); /** Fold one raw `Profiler.stop()` trace into the accumulating call-tree. */ addChunk(trace: ProfilerTrace): void; /** Close all open slices, prune single-sample runs, compact the tables, and emit the wire model. */ finish(): SliceProfile; } /** One-shot convenience: fold one trace (or an ordered list of chunks) into a `SliceProfile`. */ export declare function samplesToSlices(trace: ProfilerTrace | readonly ProfilerTrace[], opts?: SliceBuilderOptions): SliceProfile; //# sourceMappingURL=profile-slices.d.ts.map