Files
EVEngine/test/profiler.nut
T
西风逍遥游 3ac1411d85 feat(profiler): add built-in engine-wide profiler
Introduce a Tracy/UE-Insights-style scoped-zone profiler that instruments the
engine's core per-frame systems and reports per-module/per-zone self vs total
time plus GPU frame timing.

- common/Profile.* : core zone collector (eve::prof). EV_PROFILE_* RAII macros
  push {name,module,thread,parent,depth,start,end} into per-thread buffers;
  frameMark() aggregates the frame into a call tree with self/total per module
  and zone, sorted by self time. Cheap single-branch no-op when disabled.
  Lives in common/ so any module can instrument without layering violations.
- profiler module (SLOT profiler): script API setEnabled()/beginFrame()/
  endFrame()/begin()/end()/capture()/textReport()/frameMs()/gpuFrameMs().
  Installs itself as the IRenderTracer so render passes become graphics zones.
- Instrument core hot systems: physics (World/World3D), animation, particles,
  audio pump, ui render, scene transforms, map tiles, crowd, event pump.
- GPU timing: Vulkan timestamp queries around the present command buffer
  (whole-frame), exposed via common/GpuTimer.h IGpuTimer capability provided by
  graphics; read after the synchronous submit waits the in-flight fence.
- load.nut drives frameBegin()/endFrame() + section markers, no-op when absent.
- Tests: C++ unit (core aggregation self<total, render-pass zones) + script API.

Verified: all changed TUs compile against real VKBuilder/ECS/zeroerr headers;
module_depgraph.py --check / --check-layers pass. Full-link build blocked in
this env by a prebuilt third-party Squirrel version mismatch (unrelated).
2026-08-26 00:44:26 +08:00

24 lines
750 B
Plaintext

// Built-in profiler script API smoke test.
function captureWorks() {
local p = eve.Profiler();
p.setEnabled(true);
p.beginFrame();
p.begin("scriptScope");
for (local i = 0; i < 1000; ++i) { /* busy */ }
p.end();
p.endFrame();
local rows = p.capture();
if (typeof rows != "array") return false;
local found = false;
foreach (r in rows) {
if (typeof r != "table") return false;
if (!("name" in r) || !("selfMs" in r) || !("totalMs" in r)) return false;
if (r.name == "scriptScope") found = true;
}
if (!found) return false;
if (p.frameMs() < 0.0) return false;
if (p.textReport().find("scriptScope") == null) return false;
p.setEnabled(false);
return true;
}