Skip to main content

Observability

Four instruments cover the observability surface: per-node timing CSVs, the structured JSON report, graph visualization, and runtime state snapshots.

Timing output

app.run(workers=4, timing="timing.csv", output="out.txt", record=True)

timing writes a per-node timing CSV; output writes the raw timing stream. record=True enables the recording path — timing events go through a dedicated lock-free async recorder thread, so recording does not block workers. Use exclude_frames=N to drop warm-up frames from the statistics, and use_rdtsc=True on x86 for sub-microsecond timer precision (see Running graphs).

The JSON report

app.run(workers=4, report="report.json")

The report is the primary diagnostic. Its summary block carries avg/p50/p99 frame latency and throughput; summary.scheduling_overhead_diagnostic splits time into scheduling overhead versus compute (overhead_pct, overhead_us, plus an interpretation string); per_node gives per-node avg/p99 execution time and an on_critical_path flag; and optimization_suggestions is a prioritized list of category, action, knob, and estimated speedup (repository README.md). Read overhead_pct first: high values mean the graph is too fine-grained for its kernels, and the fix is coarsening, not knob tweaks.

Visualizing graphs

python -m tomii --dump graph.json --out graph.dot # GraphViz DOT topology
python -m tomii --visualize graph.json # browser view
python -m tomii --visualize graph.json --edit # browser edit mode
python -m tomii --visualize graph.json --ascii # terminal ASCII art
python -m tomii --visualize graph.json --port 8080 # custom port

The web view renders a color-coded DAG: green compute nodes, orange-bordered conditional nodes, gray post-nodes; edges styled by type ($res solid blue, $dep dashed, $barrier thick orange). Edit mode saves back to the file, and the Export Python button downloads a ready-to-run builder script for the current graph (repository README.md). The same views are available on a Graph object via app.visualize().

Runtime state snapshots

app.run(workers=4, dump_state="state.json")

dump_state (CLI --dump-state FILE) writes a JSON snapshot of per-slot runtime state at shutdown. While the process is running, sending SIGUSR1 writes numbered live snapshots FILE.1, FILE.2, ... without stopping the run:

kill -USR1 <pid>

This is the tool for wedged runs: if a frame never completes, a live snapshot shows which slots are active, which dependencies are outstanding, and how many packets are parked in the pending-frames buffer (tomii-core/src/runtime/dump.rs).

Where each tool fits

QuestionTool
Is the run fast, and why not?report.json
Which node instances are slow?timing CSV
Is the topology what I think it is?--dump / --visualize
Why is the run stuck?--dump-state + SIGUSR1

The report feeds directly into the tuning loop — see Runtime knobs.