profiler
The profiler namespace — the engine's Luau API reference for profiler.
The profiler namespace — 16 functions.
globals/profiler/begin
globals/profiler/begin(name: string)
Start a named profiling block. Call profiler.finish(name) to
record the duration. Blocks appear in profiler.stats() under
"script.<name>" and inside captures.
globals/profiler/disableRing
globals/profiler/disableRing()
Disable the ring buffer and clear its history.
globals/profiler/enableRing
globals/profiler/enableRing(seconds: number?) -> boolean
Enable the always-recording ring buffer, retaining the last
seconds of per-frame data (default 20). Query it AFTER the fact
with profiler.retro() — latency-immune, since the data is
historical. Editor profile only: returns false in the runtime
profile. The enable is the gate; the ring costs nothing until on.
globals/profiler/finish
globals/profiler/finish(name: string?) -> number?
Finish a profiling block and record the elapsed duration as
"script.<name>". Without an argument, closes the most-recently-
begun block (LIFO stack). With a name, closes the most recent
block whose name matches — useful when blocks of different names
are nested.
globals/profiler/gpuFrame
globals/profiler/gpuFrame() -> GpuFrameReport
Label-aggregated GPU pass timings of the most recent resolved
frame, measured with GPU timestamp queries. supported is false
when the device lacks timestamp queries — spans stays empty.
Each span sums every render/compute pass recorded under one label
that frame (count passes): compute.<shader> per compute
dispatch, scene.* for the scene passes, post.<effect> per
post-process effect, feature.* for render-feature passes. The
GPU may overlap passes, so total_ms can exceed frame_span_ms
(first pass begin to last pass end). The readback is asynchronous:
the report lags the live frame by a few frames. Steady per-frame
workloads read reliably; a lone one-shot dispatch submitted in
isolation can under-report on some drivers.
globals/profiler/hits
globals/profiler/hits(label: string?) -> string?
Drain the watchdog's recorded hit frames into a capture stored
under label (default "watch_hits") and clear the buffer.
Returns the capture JSON (same shape as stopCapture), or nil if
there were no hits.
globals/profiler/isCapturing
globals/profiler/isCapturing() -> boolean
Check if a profiler capture is currently active.
globals/profiler/lastCapture
globals/profiler/lastCapture() -> string?
Get the most recent completed capture result as a JSON string.
Same shape as profiler.stopCapture(). Returns nil if no capture
has been completed yet.
globals/profiler/retro
globals/profiler/retro(seconds: number?, label: string?) -> { [string]: any }?
Retroactively aggregate the last seconds of the ring (default:
the whole ring). The full per-frame capture is retained under label
(default "retro") for in-engine drill-down (profiler.frame/hotspots);
this RETURNS a compact structured aggregate table (frame-time distribution
- per-system summary), never the raw per-frame array — bounded, so it is
safe over the ZeroMind bridge. Code-facing primitive; the
retrotool renders the agent-facing report. Latency-immune: the data is historical.
globals/profiler/ringStatus
globals/profiler/ringStatus() -> string
Ring buffer status as a JSON string:
{ enabled, frames, capacity, span_seconds }.
globals/profiler/startCapture
globals/profiler/startCapture(label: string?) -> boolean
Start recording per-frame profiler data. Each frame's system
timings are captured until stopCapture() is called. Results are
accessible via profiler.lastCapture() and VFS at
/zero/runtime/profiler/<label>.json.
globals/profiler/stats
globals/profiler/stats(pattern: string?) -> { ProfilerStat }
Get current EMA profiling statistics from the SystemProfiler.
Optional glob pattern filters by metric name (supports * and ?
wildcards).
globals/profiler/stopCapture
globals/profiler/stopCapture() -> string?
Stop the active profiler capture and return its result as a
JSON string. The capture is also saved to VFS at
/zero/runtime/profiler/<label>.json. Top-level fields: label,
frame_count, started_at, ended_at, frames, summary.
Compute duration as ended_at - started_at.
globals/profiler/unwatch
globals/profiler/unwatch()
Disarm the watchdog. Recorded hits are kept for a final
profiler.hits().
globals/profiler/watch
globals/profiler/watch(ceilingMs: number, mode: string?, excludeAgent: boolean?, maxHits: number?) -> boolean
Arm the frame-time watchdog. When a frame's EFFECTIVE time
(total minus agent-injected execute cost) crosses ceilingMs,
mode "record" logs every offending frame (read with
profiler.hits()), and mode "pause" pauses gameplay ONCE to
freeze the bad state, then disarms. Editor profile only: returns
false in the runtime profile. excludeAgent (default true) keeps
the agent's own calls from tripping it.
globals/profiler/watchStatus
globals/profiler/watchStatus() -> string
Watchdog status as a JSON string: { armed, ceiling_ms, mode, exclude_agent, hits, dropped_hits, tripped }.