---
title: Measuring
description: Measure the thing you intend to optimize: CPU encoding, pipeline warm-up, bind-group churn, target memory, or shader cost. The public API makes those boundaries visible.
---

# Measuring



## CPU encoding vs replay

If the CPU is busy rebuilding the same render pass, compare a direct loop with a bundle:

```text
const staticScene = bundle(gpu, { target }, (b) => staticDraws.forEach((draw) => b.draw(draw)));
frameLoop(gpu, (f) => f.pass({ target }, (p) => p.bundles(staticScene)));
```

## First-frame hitches

If the first visible frame stutters, pre-warm target signatures with `compile()`:

```text
const hdr = target(gpu, { size: [256, 256], format: "rgba16float", depth: true, msaa: true });
const draw = draw(gpu, { shader: WGSL, mesh });
await draw.compile(hdr);
```

## Binding churn

If allocations or bind-group count grows every frame, switch repeated JS values to in-place `set()`, shared state to `uniforms(gpu)`, or many object uniforms to `UniformPool` + dynamic offsets.

## GPU pass cost

If a pass looks expensive, confirm it on the GPU before optimizing it. CPU time around `frame.pass(...)` measures encoding only — encoders record commands, they do not run them. Mark the pass with a `timer(gpu)` span instead:

```text
const gpu = await init({ requiredFeatures: ["timestamp-query"] });
const timer = timer(gpu);
timer.onResults((spans) => console.log(`shadows ${spans.shadows}ms, main ${spans.main}ms`));
frameLoop(gpu, (f) => {
  f.pass({ target: shadowMap, timer: timer.span("shadows") }, (p) => p.draw(casters));
  f.pass({ target: scene, timer: timer.span("main") }, (p) => p.draw(world));
});
```

Durations arrive through `onResults` in milliseconds, one or two frames after submit; readback never blocks a frame. A span times the whole pass, not individual draws — move suspect work into its own pass to isolate it.

## Correctness before speed

When measuring visual output, render one deterministic `frame(gpu, ...)` into an explicit target and read it back. Do not measure while also resizing, compiling pipelines lazily, or creating temporary targets inside the loop.


---

For a semantic overview of all documentation, see [/sitemap.md](/sitemap.md)

For an index of all available documentation, see [/llms.txt](/llms.txt)

For agent-facing discovery, including API and MCP surfaces, see [/agents.md](/agents.md)