Profiling
This file covers the engine’s trace: one timeline per run on which every thread’s zones nest,
device work sits as its own tracks, and warnings appear where they were logged. It was built by
H6a of BETA_HARDENING.md and is not yet built by the owner; the
decisions behind it are in ENGINE_DIAGNOSTICS.md §7. The
types and their files are listed in engine/foundation/profiling/README.md.
1. The timeline
A capture is a window of time. While it runs, each thread writes begin and end events into its
own fixed ring (ThreadTraceBuffer, 65,536 events of 24 bytes by default) with no lock. A full
ring drops the event and counts the drop. When the capture stops, TraceRecorder drains every
ring on the stopping thread into a TraceCapture, closes any zone still open at the capture’s
end, drops any end whose begin came before the capture, and converts ticks to steady-clock
nanoseconds.
Zones read the invariant TSC through TraceClock. The drain converts ticks through two
calibration points, one taken at start and one at stop. On a CPU without an invariant TSC the
clock falls back to steady_clock and the start result says so.
When no capture runs, a compiled-in zone costs one relaxed atomic load and a branch. At
SUSHIENGINE_PROFILE_LEVEL=0 the zone macros compile to nothing.
2. Tracks
| Track | Written by | What is on it |
|---|---|---|
| A thread | SE_ZONE and SE_ZONE_FINE on that thread |
Nested zones: the frame, simulation phases, the ECS schedule, job batches (and job blocks at level 2), render stages through ScopedTimer |
| Lock waits | ContendedLock, SE_ZONE_LOCK_WAIT |
A zone on the waiting thread, only when try_lock failed |
| Log markers | TraceLogSink in engine/foundation/logging |
An instant marker for each warning and error, on the thread that logged it |
gpu |
GPUProfiler::resolve |
One span per render pass, in steady nanoseconds through VK_KHR_calibrated_timestamps; named gpu uncalibrated without the extension, anchored at begin_frame |
| One per SYCL queue | engine/foundation/execution/include/SushiEngine/execution/run_report_trace.hpp in engine/foundation/execution |
One span per RunReport node event, for ECS systems and the matter solver |
One per Device channel |
FrameProfiler::record_interval |
The interval the Profiler panel also shows |
There is one GPU track, so graphics and async-compute spans can overlap on it.
3. Backends
The zone macros call a small seam in
engine/foundation/profiling/include/SushiEngine/profiling/zone.hpp (zone_begin, zone_end,
device_span, capture_changed, set_thread_name). Exactly one translation unit defines it,
picked at configure time by SUSHIENGINE_PROFILER_BACKEND:
- builtin (the default):
engine/foundation/profiling/source/trace_backend_builtin.cppwrites to the recorder, andwrite_chrome_traceturns a capture into Chrome trace JSON. - tracy:
engine/foundation/profiling/source/trace_backend_tracy.cppforwards to Tracy’s client, found only when the owner has installed it through sushistack ([tracy]incli/sushistack.deps.toml, port featurescore,on-demand). Zones go to___tracy_emit_zone_begin/_endwith theZoneSiteaddress, whose first five fields are Tracy’s source location. The zone gate stays open for the whole run: withTRACY_ON_DEMANDTracy itself drops a zone while no viewer is connected, so an idle zone costs the gate load, a call and Tracy’s connection check. Each device track becomes one Tracy GPU context (type Custom, period 1 ns), created on the track’s first span while a viewer is connected, aligned once to Tracy’s clock by passing the steady-clock time at creation, and named after the track’s queue throughTraceRecorder::device_track_name. A span is one GPU zone with two query ids whose times are itsstart_nsandend_ns. The built-in recorder still links but receives nothing, so a Tracy build writes no Chrome trace. The backend has passed a syntax check against Tracy 0.13.1’s headers and has not been built.
4. Capturing
se editor --trace out.json and se player --trace out.json record from launch to exit; the
editor’s Profiler panel starts and stops a capture on demand and writes it under the project’s
logs folder. Perfetto (ui.perfetto.dev) and chrome://tracing open the file. The flags are
described in the command line guide.

