flame-graph — CPU Profiler
Generates SVG flame graphs for every ResQ service. Each subcommand knows how to profile its target: calling the right endpoint, running the right profiler binary, and piping the output through inferno-flamegraph.
Prerequisites
# inferno — converts folded stack traces to SVG (required for all subcommands)
# py-spy — Python profiler (required for pdie / python subcommands)
# perf — Linux kernel profiler (required for offcpu subcommand)
# Usually installed via: sudo apt install linux-perf or sudo pacman -S perf
Build
Binary: tools/flame-graph/target/release/flame-graph
Subcommands
Service Profilers
hce — coordination-hce (Node.js/Bun)
Connects to the node:inspector Session API exposed by the HCE service to take a V8 CPU profile.
Requires the service to be running with --inspect or with the /admin/cpu-profile endpoint enabled.
api — infrastructure-api (Rust/pprof-rs)
Hits the /admin/profile endpoint which triggers pprof-rs CPU sampling (SIGPROF-based).
Returns folded stacks in the pprof protobuf format, converted internally to the inferno input format.
pdie — intelligence-pdie (Python/py-spy)
Attaches py-spy to the running PDIE process and samples its call stack.
Requires py-spy on PATH and the ability to attach to the process (may need sudo on some systems).
General Profilers
python <pid> — Attach py-spy to any Python process
file <path> — Convert existing folded stacks file to SVG
Input format: one line per stack sample in inferno folded format:
root;parent;leaf 42
root;parent;other_leaf 17
perf — Linux perf record + perf script
Runs perf record on a PID for the given duration, then converts the output.
# Profile a specific PID
# Profile a command
bun — Bun runtime CPU profile
Collects a Bun CPU profile by attaching to the running Bun process.
dotnet — .NET simulation-harness
Generates a flame graph for the .NET simulation-harness using dotnet-trace.
Internally runs:
dotnet-trace collect --process-id <pid> --providers cpu-sampling --duration 00:00:<N>
Analysis Subcommands
offcpu — Off-CPU time analysis
Captures time threads spend blocked (I/O, locks, syscalls) rather than running on CPU.
Requires perf with eBPF support or bpftrace.
diff — Differential flame graph
Compares two folded stack files and highlights regressions in red, improvements in blue.
hotcold — Hot/cold flame graph
Color-codes frames by sample frequency: red (hot) → blue (cold).
memory — Memory allocation flame graph
Profiles heap allocations rather than CPU time.
# Rust (via jemalloc profiling)
# Python (via tracemalloc snapshot)
explain — AI-assisted analysis
Sends the top frames from a flame graph to the Gemini AI endpoint for plain-English explanation of hot spots.
Common Flags
| Flag | Default | Description |
|---|---|---|
--url <url> |
service default | Service base URL |
--token <jwt> |
$RESQ_TOKEN |
Bearer token (HCE) |
--api-key <key> |
$RESQ_API_KEY |
API key (infra-api, pdie) |
--duration <secs> |
30 |
Profile duration in seconds |
--output <path> |
flamegraph.svg |
Output SVG path |
--pid <pid> |
— | Target process ID |
Reading Flame Graphs
- Width of a frame = proportion of total samples where that function was on the stack
- Height = call depth (bottom = root, top = leaf)
- Wide frames at the top = hot leaf functions — primary optimization targets
- Wide frames in the middle = called frequently from many paths
Open the SVG in a browser for interactive search (Ctrl+F) and zoom by clicking frames.
Typical Workflow
# 1. Start services
# 2. Generate load (simulation harness or curl loop)
&&
# 3. Profile while load is running
# 4. Make optimization changes, restart, repeat
# 5. Compare
Full Documentation
See docs/PROFILING_FLAMEGRAPH_GUIDE.md for all subcommands, auth setup, and worked examples.