mirror of
https://github.com/vector-im/element-call.git
synced 2026-09-22 22:29:30 +00:00
Ask the bench where the startup went
- Splits attaching from switching: building the segmenter fetches, compiles and sets up the GPU, while switching only tells a built one what to draw. One of those can be paid ahead of time. - Reports the segmenter's assets as the browser saw them. A transfer size of zero means cache, which is what separates the first run on a device from every run. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -61,8 +61,27 @@ interface Run {
|
|||||||
sdkWouldAllow: boolean;
|
sdkWouldAllow: boolean;
|
||||||
capture: { width?: number; height?: number; frameRate?: number };
|
capture: { width?: number; height?: number; frameRate?: number };
|
||||||
processed: { width?: number; height?: number; frameRate?: number };
|
processed: { width?: number; height?: number; frameRate?: number };
|
||||||
/** Milliseconds from asking for the effect to the first frame carrying it. */
|
/** Milliseconds from asking for the effect until the pipeline reports ready. */
|
||||||
startupMs: number | null;
|
startupMs: number | null;
|
||||||
|
/**
|
||||||
|
* Where that time went: attaching builds the segmenter — fetching its
|
||||||
|
* assets, compiling the WASM, setting up the GPU — while switching only
|
||||||
|
* tells an already-built one what to draw. Split, because the two have
|
||||||
|
* different answers: one can be paid ahead of time, the other cannot.
|
||||||
|
*/
|
||||||
|
attachMs: number | null;
|
||||||
|
switchMs: number | null;
|
||||||
|
/**
|
||||||
|
* The segmenter's own assets, as the browser saw them. A transfer size of
|
||||||
|
* zero means the bytes came from cache and no network was involved, which is
|
||||||
|
* what separates "the first time on this device" from "every time".
|
||||||
|
*/
|
||||||
|
assets: {
|
||||||
|
name: string;
|
||||||
|
transferredBytes: number;
|
||||||
|
bytes: number;
|
||||||
|
ms: number;
|
||||||
|
}[];
|
||||||
meanFps: number;
|
meanFps: number;
|
||||||
/** The worst five-second stretch — where throttling shows up first. */
|
/** The worst five-second stretch — where throttling shows up first. */
|
||||||
worstFps: number;
|
worstFps: number;
|
||||||
@@ -115,6 +134,8 @@ export const BackgroundEffectsBench: FC = () => {
|
|||||||
const capture = track.mediaStreamTrack.getSettings();
|
const capture = track.mediaStreamTrack.getSettings();
|
||||||
|
|
||||||
let startupMs: number | null = null;
|
let startupMs: number | null = null;
|
||||||
|
let attachMs: number | null = null;
|
||||||
|
let switchMs: number | null = null;
|
||||||
if (effect !== "none") {
|
if (effect !== "none") {
|
||||||
setStatus("Starting the pipeline…");
|
setStatus("Starting the pipeline…");
|
||||||
const askedAt = performance.now();
|
const askedAt = performance.now();
|
||||||
@@ -123,8 +144,12 @@ export const BackgroundEffectsBench: FC = () => {
|
|||||||
"background-effect-bench",
|
"background-effect-bench",
|
||||||
);
|
);
|
||||||
await track.setProcessor(pipeline);
|
await track.setProcessor(pipeline);
|
||||||
|
const attachedAt = performance.now();
|
||||||
await pipeline.switchTo(optionsFor(effect));
|
await pipeline.switchTo(optionsFor(effect));
|
||||||
startupMs = Math.round(performance.now() - askedAt);
|
const readyAt = performance.now();
|
||||||
|
attachMs = Math.round(attachedAt - askedAt);
|
||||||
|
switchMs = Math.round(readyAt - attachedAt);
|
||||||
|
startupMs = Math.round(readyAt - askedAt);
|
||||||
}
|
}
|
||||||
|
|
||||||
const element = video.current!;
|
const element = video.current!;
|
||||||
@@ -157,6 +182,9 @@ export const BackgroundEffectsBench: FC = () => {
|
|||||||
frameRate: processed.frameRate,
|
frameRate: processed.frameRate,
|
||||||
},
|
},
|
||||||
startupMs,
|
startupMs,
|
||||||
|
attachMs,
|
||||||
|
switchMs,
|
||||||
|
assets: segmenterAssets(),
|
||||||
...result,
|
...result,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
@@ -229,7 +257,12 @@ export const BackgroundEffectsBench: FC = () => {
|
|||||||
<div key={i} style={{ marginBlockStart: 12 }}>
|
<div key={i} style={{ marginBlockStart: 12 }}>
|
||||||
<strong>{run.effect}</strong>: mean {run.meanFps.toFixed(1)}fps, worst{" "}
|
<strong>{run.effect}</strong>: mean {run.meanFps.toFixed(1)}fps, worst{" "}
|
||||||
{run.worstFps.toFixed(1)}fps
|
{run.worstFps.toFixed(1)}fps
|
||||||
{run.startupMs !== null && <>, pipeline ready in {run.startupMs}ms</>}
|
{run.startupMs !== null && (
|
||||||
|
<>
|
||||||
|
, ready in {run.startupMs}ms ({run.attachMs}ms attaching,{" "}
|
||||||
|
{run.switchMs}ms switching)
|
||||||
|
</>
|
||||||
|
)}
|
||||||
, first frame at {run.firstFrameMs ?? "?"}ms, picture stopped for up
|
, first frame at {run.firstFrameMs ?? "?"}ms, picture stopped for up
|
||||||
to {run.worstFrameGapMs}ms, main thread stalled up to{" "}
|
to {run.worstFrameGapMs}ms, main thread stalled up to{" "}
|
||||||
{run.worstTimerLagMs}ms
|
{run.worstTimerLagMs}ms
|
||||||
@@ -246,6 +279,24 @@ export const BackgroundEffectsBench: FC = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* What the browser did to fetch the segmenter: bytes over the wire, bytes
|
||||||
|
* total, and how long each took. Same-origin, so the sizes are not hidden.
|
||||||
|
*/
|
||||||
|
function segmenterAssets(): Run["assets"] {
|
||||||
|
return performance
|
||||||
|
.getEntriesByType("resource")
|
||||||
|
.filter((e): e is PerformanceResourceTiming =>
|
||||||
|
/\.(wasm|tflite|task|binarypb)(\?|$)/.test(e.name),
|
||||||
|
)
|
||||||
|
.map((e) => ({
|
||||||
|
name: e.name.slice(e.name.lastIndexOf("/") + 1),
|
||||||
|
transferredBytes: e.transferSize,
|
||||||
|
bytes: e.encodedBodySize,
|
||||||
|
ms: Math.round(e.duration),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Counts frames as the video actually presents them, which is the rate the
|
* Counts frames as the video actually presents them, which is the rate the
|
||||||
* pipeline is really delivering rather than the rate it was asked for.
|
* pipeline is really delivering rather than the rate it was asked for.
|
||||||
|
|||||||
Reference in New Issue
Block a user