devuiGuideDemosAPIGitHub

Performance and plots

gui.perf() adds a Performance folder, in place of stats.js. It's a plot each of frame time, CPU time, GPU time and memory, each on a scale of its own, so a tenth of a millisecond of GPU time reads as clearly as a 16 ms frame. Each plot's name, readout and note are written over its graph, and each has every plot's controls (below). A note is numbers only. Where a time comes from, or why there's none, is in the plot's tooltip.

GPU time is measured given a context (gui.perf({ gl })), through EXT_disjoint_timer_query_webgl2:

const perf = gui.perf({ gl });
perf.begin('shadows'); drawShadows(); perf.end('shadows');   // or perf.time('shadows', drawShadows)

gui.perf({ folder: 'Stats' }) puts the folder elsewhere. perf.stats holds the readouts (fps, 1% low, long frames, frame ms, cpu ms, gpu ms, heap MB) for your own use. The plots are perf.plot, perf.cpuPlot, perf.gpuPlot and perf.memory (Performance/frame, /cpu, /gpu and /memory, which an agent's read_plot reads).

Compact meters. perf.compact(), or the palette's Performance meters, shows the gpu, cpu and memory plots small, side by side, in a window of their own, about 300 × 50 px, with no title bar. They're read by hovering alone, their readouts without notes; the full folder has their controls and notes.

Drag the window by any part of it but its buttons. A double-click, or its expand button, turns it into the Performance folder, where it is; the folder window's compact button turns it back. Where it was left is kept with the layout. The meters are the folder's window in its compact form, so while they're open the folder isn't in the panel too; closing them puts it back there.

const perf = gui.perf({ gl, compact: true });      // start as the meters, top-left ('bottom-right'…)
perf.compact('top-right');                          // or later; perf.expand() for the folder

CPU and GPU time are the frame section's, or else every named section's together. A section inside another one counts in both, on the CPU and the GPU; one inside another of its own name is part of it. devui's own drawing on your context (texture views) isn't counted, nor are passes while your app times its own work with a timer query (they can't nest): each of those counts as it typically takes. With the three.js extension, renderer.render is a section (render, its calls summed per frame). Code that uses stats.js can alias it to @haxiomic/devui/compat/stats, which drives gui.perf() instead (the engine demo does this).

Where timer queries can't time a pass (on Chrome on macOS: see the frame scope, under GPU time), no queries are made: their sum would be many frames' worth, and even one around the frame reads up to twice its time. The gpu plot is the whole frame's time from a fence instead, from its first GPU work until the GPU finished it, without stalling anything. It's good to about 2 ms and counts JavaScript the GPU may have been idle through; its tooltip says so. The frame scope times each pass there, over frames.

Plots can be hovered, paused, measured and zoomed:

Vector and colour monitors (gui.monitor(body, 'velocity', { view: 'graph' })) plot one series per component, in the usual x/y/z colours.

A plot's options, as the Performance folder's use them:

const p = gui.plot('step ms', { unit: 'ms', min: 0, overlay: true, half: true, guide: 16.7, colors: ['--series-2'] });
p.setNote('physics and AI');