| name | stax |
| description | Profile a program with stax (live CPU stacks, off-CPU waits, target/GPU spans, annotated disassembly) to find where time actually goes. Use whenever you need to measure performance, find hot functions, or answer "why is this slow" instead of guessing. Covers building with the right debug symbols, record → wait → flame → top → annotate, the flame-before-top rule, on-CPU vs off-CPU, and where the full reference lives. |
stax is a live profiler driven entirely from the CLI: record a program, then
query the run while it is still going (or after it exits — the run stays in
the server's query state). Text output, meaningful exit codes; works over SSH,
in CI, and from an agent.
This skill is the quickstart plus the habits that matter. It is not the
complete reference. The authoritative docs are:
AGENTS.md in the stax repo — full subcommand reference, daemon/concurrency
model, run lifecycle, RPC services, common pitfalls. Read it for anything below.
- https://stax.bearcove.eu — guide, concepts, install, platform/unwinding details.
stax --help, stax <cmd> --help, stax --html-help — exact flags. Plus a
web UI (timeline + flamegraph) when you want one; nothing depends on it.
Rule #1: measure, never guess
If a question is measurable, measure it. Do not theorize about why something is
slow, which function dominates, or whether a path is hot — record it and read
the profile. A loaded profile answers most "why" questions for free; reaching
for source-reading or a hunch first is the mistake.
Build for profiling: get the symbols right BEFORE recording
A profiler is only as good as the symbols in the binary. Get this right first or
every later view is degraded.
Workflow
-
Profile the built binary, not cargo run (that profiles the compile too).
Build with symbols (above), then stax record -- ./path/to/bin …, or attach
with stax record --pid <PID>. Defaults: 900 Hz (-F), runs until the target
exits (-l <secs> to cap). The target launches suspended so you catch startup;
on exit the run is left in query state automatically.
-
If the target is still running, wait for data:
stax wait --for-samples 10000
-
stax flame FIRST. Always. The load-bearing step.
stax flame -d 12 --threshold-pct 1
Prints the call tree as an indented tree with each frame's share of total
active time: caller → callee, siblings side by side. It tells you what is
expensive and how the costs nest (stacked under one parent vs. independent
siblings) — that structure is the answer to most perf questions, drawn for you.
-d caps depth (deeper → …<N more frames>), --threshold-pct hides small
frames (0 = all), --tid filters one thread.
-
stax top is for drilling AFTER flame — not for rebuilding the tree.
stax top -n 20 --sort self
stax top -n 20 --sort total
top is a flat ranking of frames in isolation; it shows no nesting. Use it
to confirm a leaf you already located in the flame, or to read exact sample
counts. If you catch yourself mentally reassembling a call tree from top,
stop and run flame — that exact move is how you guess the trunk wrong.
-
stax annotate → instruction level (needs the debug info from step "Build"):
stax annotate 'mycrate::hot_fn'
Per-instruction sample counts interleaved with source; hottest matching leaf wins.
Reading the numbers
- on-CPU vs off-CPU.
flame/top rank active (on-CPU) time. A run can
show a large off-CPU total — time blocked on locks, sleep, I/O, IPC, not
burning CPU. Small active + huge off-CPU = the program is mostly waiting. Use
stax threads -n 20 for the per-thread on-CPU / off-CPU / target-lane split,
and stax correlates the scheduler event so you see why it blocked.
- target/executor spans (
target ms / spans columns) are exact-duration
work reported by an app linking stax-target — GPU kernels, accelerator
queues, executors. Rank them with stax target lanes / stax target top --by time|count|avg|max; with origins, flame renders CPU dispatch → lane →
named work.
Runs: inspect, save, compare (incl. CI gating)
stax status
stax list
stax top --run <ID>
stax select-run <ID>
stax save out.stax
stax open out.stax
stax compare base.stax cand.stax
stax compare --json --fail-active-delta-ms 50 base.stax cand.stax
stax diagnose
stax dump
Setup (once per machine)
stax needs privileged sampling access. stax setup codesigns the binary
(macOS); run as root it installs the staxd helper (LaunchDaemon on macOS;
see AGENTS.md "Install" for Linux stax-server + staxd). Do this before
recording.
Anti-patterns
- Profiling
cargo run … — you measure the build. Build, then record the artifact.
- Recording a stripped /
debug = false binary and then being surprised by
raw addresses or annotate with no source. Set up the profiling profile first.
- Reading
top and reasoning about the call graph from the flat list — the
trap. flame shows the graph.
- Concluding a function is the bottleneck by reading code. Record and read the flame.
- Treating a big off-CPU total as CPU cost — check
stax threads; it may be waiting.
- Treating this skill as the whole map. For any command's full behavior, read
AGENTS.md and stax <cmd> --help.