/** * The `p`th percentile (0..100) of `values`, by linear interpolation between * closest ranks - the same definition as NumPy's default and a spreadsheet's * PERCENTILE. Returns null for an empty input rather than inventing a zero. */ export declare function percentile(values: readonly number[], p: number): number | null; /** Consecutive differences of a monotonic series of timestamps. */ export declare function intervals(timestamps: readonly number[]): number[]; /** Fixed-width histogram of `values`, with an explicit overflow bucket. */ export declare function histogram(values: readonly number[], bucketMs?: number, buckets?: number): Histogram; /** * Snap a measured frame period to the nearest common refresh rate when it is * within `tolerance` of one, so 8.33 ms reads as 120 Hz rather than 120.05 Hz. * Returns the unsnapped rate when nothing is close. */ export declare function snapRefreshRate(periodMs: number, tolerance?: number): number; /** * Frames that should have been presented and were not. * * An interval of 2.0 periods means one frame was skipped; 1.4 periods is late * but not a skipped frame. Rounding is the usual convention (it matches what a * frame-time graph shows as a missing bar). */ export declare function droppedFrames(frameIntervals: readonly number[], periodMs: number): number; /** * Summarise a run of `requestAnimationFrame` timestamps against a target rate. * * `targetHz` should be the display's refresh rate when it is known, because * that is the rate a game wants. Pass the rate rAF itself runs at to count * drops against what the web view actually delivers - the two differ when the * web view caps rAF below the display (WebKit's 60 Hz cap on ProMotion panels). */ export declare function framePacing(timestamps: readonly number[], targetHz: number): FramePacingStats | null; /** Percentile summary of latency samples, or null when there were none. */ export declare function latency(samples: readonly number[]): LatencyStats | null; /** * The refresh rate in a `system_profiler SPDisplaysDataType` resolution string * such as `1512 x 982 @ 120.00Hz`, or null when it names none. */ export declare function parseRefreshHz(resolution: string | undefined): number | null; /** * The arithmetic behind the interactive-content probe (stacksjs/stacks#877). * * Kept pure and DOM-free so the numbers the probe page reports can be checked * without a window: the page collects raw `requestAnimationFrame` timestamps and * event-to-frame deltas, and everything that turns those into a histogram, a * percentile or a dropped-frame count lives here, where a unit test can reach it. */ /** Refresh rates a display can plausibly run at, used to snap a measured period. */ export declare const COMMON_REFRESH_RATES: readonly number[]; export declare interface Histogram { bucketMs: number counts: number[] overflow: number } export declare interface FramePacingStats { frames: number durationMs: number fps: number p50Ms: number p95Ms: number p99Ms: number maxMs: number targetPeriodMs: number targetHz: number droppedFrames: number longFrames: number histogram: Histogram } export declare interface LatencyStats { samples: number p50Ms: number p95Ms: number maxMs: number }