novaphy.PerformanceMonitor¶
Thread-local profiling utility. Wrap a step in with monitor.scoped(): ...
to capture aggregate per-phase timings and (optionally) emit a Chrome /
Perfetto trace. Outside the with block every C++ phase scope is a zero-cost
no-op, so solver public APIs stay free of profiling parameters.
This mirrors Newton's EventTracer / event_scope pattern.
Attributes¶
| Attribute | Description |
|---|---|
enabled |
Enable aggregate capture for future scoped frames. |
trace_enabled |
Enable per-frame trace recording for write_trace_json. A scoped frame still captures when this is True even if enabled is False. |
trace_frame_capacity |
Maximum number of recent profiled frames retained for trace export. Default: 120; setting a negative value clamps it to zero. |
frame_count |
Read-only number of profiled frames captured since the last reset. |
last_frame_total_ms |
Read-only wall-clock duration of the most recently completed profiled frame. |
Methods¶
| Method | Description |
|---|---|
scoped() |
Context manager. Capture the wrapped block. |
reset() |
Clear aggregate statistics, last-frame metrics, and buffered trace data. |
begin_frame() |
Manually start a profiled frame. Prefer scoped() unless manual lifecycle control is required. |
end_frame() |
Finish and commit a frame opened by begin_frame(). |
record_metric(name, value) |
Record a numeric metric in the current profiled frame. |
phase_stats() |
Aggregate stats list (PerformancePhaseStat). |
last_frame_metrics() |
Per-frame metric list (PerformanceMetric). |
write_trace_json(path) |
Write a Chrome / Perfetto trace JSON. |
Example¶
import novaphy
monitor = novaphy.PerformanceMonitor()
monitor.enabled = True
monitor.trace_enabled = True
for _ in range(120):
with monitor.scoped():
solver.step(state, state, control, contacts, dt)
for stat in monitor.phase_stats():
print(stat.name, stat.avg_ms)
monitor.write_trace_json("trace.json")