Documentation

Installation & Usage

Get started with SPAA in minutes

Installation

SPAA is distributed as a Rust crate and can be installed via Cargo. This installs three binaries: dtrace_to_spaa, chrome_to_spaa, and heapdiff.

cargo install spaa

Prerequisites: You need Rust and Cargo installed. If you don't have them, install via rustup.rs

Quick Start

Convert a DTrace profile

Run DTrace to collect a CPU profile, then convert it to SPAA format:

1. Collect profile with DTrace
sudo dtrace -n 'profile-997 { @[ustack()] = count(); }' -o profile.txt
2. Convert to SPAA
dtrace_to_spaa profile.txt -o profile.spaa

Convert Chrome DevTools data

Convert CPU profiles or heap snapshots from Chrome DevTools:

CPU profiling (Performance panel trace or .cpuprofile)
chrome_to_spaa trace.json -o cpu.spaa
Memory profiling (heap snapshot or heap timeline)
chrome_to_spaa Heap.heapsnapshot -o heap.spaa

Find memory leaks with heapdiff

Compare two Chrome heap snapshots to identify memory leaks:

heapdiff baseline.heapsnapshot after-action.heapsnapshot -o diff.ndjson

CLI Tools

dtrace_to_spaa

Converts DTrace aggregated stack output to SPAA format.

dtrace_to_spaa input.txt -o output.spaa
dtrace_to_spaa input.txt --event syscall::read:entry --frequency 0

Options

-o, --outputOutput file (defaults to input with .spaa extension)
-e, --eventEvent name (default: profile-997)
-z, --frequencySampling frequency in Hz (inferred from event name if possible)
-f, --formatInput format: aggregated (default), split, per-probe

chrome_to_spaa

Converts Chrome DevTools profiling data to SPAA format. Automatically detects the input type.

chrome_to_spaa trace.json        # Performance panel trace
chrome_to_spaa profile.cpuprofile # V8 CPU profile
chrome_to_spaa Heap.heapsnapshot  # Memory panel snapshot
chrome_to_spaa timeline.heaptimeline # Allocation timeline

Options

-o, --outputOutput file (defaults to input with .spaa extension)

heapdiff

Compares two Chrome heap snapshots to identify memory leaks. Outputs an agent-friendly NDJSON format showing object type growth and retention paths.

heapdiff baseline.heapsnapshot target.heapsnapshot -o diff.ndjson

Options

-o, --outputOutput file (defaults to stdout)
-n, --max-retainedMaximum retained objects to analyze (default: 100)

Library Usage

The spaa_parse crate provides types and parsers for working with SPAA files in Rust:

use spaa_parse::{SpaaReader, Record};
use std::fs::File;
use std::io::BufReader;

let file = File::open("profile.spaa")?;
let reader = SpaaReader::new(BufReader::new(file));

for record in reader {
    match record? {
        Record::Header(h) => println!("Source: {}", h.source_tool),
        Record::Stack(s) => println!("Stack {} has {} frames", s.id, s.frames.len()),
        _ => {}
    }
}
AI Agent

Agent Skill

Install the SPAA analysis skill to give your AI coding agent the ability to analyze performance profiles:

npx skills add andrewimm/spaa

The skill teaches agents how to:

  • Parse SPAA files using head, tail, grep, and jq
  • Find CPU hotspots and hot functions (exclusive time)
  • Identify memory leaks via live_bytes metrics
  • Reconstruct call stacks from frame IDs
  • Filter by thread, event type, or time window

Claude Code

Supported

Cursor

Supported

Skills-compatible

Supported

Working with SPAA Files

SPAA files are NDJSON (newline-delimited JSON), making them easy to query with standard command-line tools:

View the header (first line)

head -1 profile.spaa | jq .

Find all stack records

grep '"type":"stack"' profile.spaa | head -5

Extract frame information

grep '"type":"frame"' profile.spaa | jq '{id, func, srcline}'

Find hottest stacks by sample count

grep '"type":"stack"' profile.spaa | \
  jq -r '[.weights[] | select(.metric=="samples") | .value][0] as $v | "\($v)\t\(.id)"' | \
  sort -rn | head -10

Filter stacks by thread ID

grep '"type":"stack"' profile.spaa | jq 'select(.context.tid == 4511)'