Log inGet started

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 retro tool 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 }.

  • api
  • reference