Skip to content

RuntimeMetrics ​

runtime.metrics registers metrics on runtime.stats, the one recorder behind the corner HUD and the readout panel. Setup recipes are in frame scheduling and performance.

ts
const release = runtime.metrics.addSource(engine.inspector);

Properties ​

PropertyTypeDescription
rendererRendererMetricsThe renderer counters.
panelMetricsPanel | nullThe mounted readout panel.

Methods ​

MethodDescription
addSource(source)Registers every metric of a MetricSource and returns a release function. Call it when the source dies before the runtime; a leftover metric keeps sampling it.
addMetric(definition)Registers one MetricDefinition and returns a release function.
removeMetric(id)Removes a metric. Returns false when the id is unknown.
track(id, value)Pushes a value to a metric, as StatsRecorder.track().
mountPanel(options?)Mounts the readout panel and disposes the previous one. runtime.mountMetricsPanel() adds the world keyboard.
dispose()Called by runtime.dispose().

Renderer counters ​

The runtime registers the WebGPURenderer counters under the renderer group, outside the HUD cycle: calls, renderedTriangles, geometries, textures, and the byte counts geometryMemory and textureMemory.

A renderer created with timestamp tracking also gets gpuTime, the GPU milliseconds of the last drawn frame, read back after every "draw":

ts
const runtime = await Runtime.create(canvas, {
  renderer: {
    webgpu: {
      trackTimestamp: true
    }
  }
});

Three.js turns tracking off on a device without the timestamp-query feature, and the metric is then absent. Every read-back copies the queries out of the GPU, so keep tracking off outside measurements. A frame drawn while the previous read-back is still pending is added to the next value.

Three.js resets renderer.info.render on every animation-loop tick, including the ticks the maxFps cap skips, so a read outside a "draw" handler mostly sees zero. Read renderer.frame instead:

ts
const { drawCalls, triangles } = runtime.metrics.renderer.frame;

It returns a new RendererFrameStats on every read. drawCalls and triangles come from the last drawn frame; geometries and textures are live. To refresh a display at the recorder's pace, read it from runtime.stats.subscribe().

MetricsPanel ​

The readout lists one folder per metric group and one row per metric. Metrics registered later join it on their own.

MemberDescription
containerFacadeContainer holding the rows. Add your own controls to it.
hiddenShows or hides the readout.
dispose()Removes the readout.

MetricsPanelOptions ​

OptionDefaultDescription
targetfloats over the pageAn HTMLElement receives a pane of its own; a FacadeContainer takes the folders directly.
floatingfalseFloats the pane inside an HTMLElement target. Target a jolly-dock-layout to make it dockable.
keynoneIdentity the pane persists and docks under. Required to dock.
title"Performance"Pane heading. Unused with a FacadeContainer.
storageKeynoneNamespace the pane persists under.
toggleKeynoneKeyboardEvent.code toggling hidden, read from keyboard.
keyboardworld keyboard, through runtime.mountMetricsPanel()Emits the toggleKey events.
hiddenfalseStarts hidden.
collapsibletrueLets the created pane fold to its header.
filternoneKeeps only the metrics it accepts, later ones included. (metric) => metric.tile === false drops what the HUD already cycles.
signalnoneAbortSignal that unmounts the panel and clears panel. Aborted before mountPanel() resolves, the mount is dropped and the current panel stays.