Loading...
Loading...
Guidance for interpreting SPAA (Stack Profile for Agentic Analysis) files. Provides information on the file format, as well as tips on how to use it to identify performance bottlenecks, memory leaks, or opportunities for optimization. Use when the user is trying to read a .spaa file to understand the performance of an application.
npx skill4agent add andrewimm/spaa spaatypehead -1 profile.spaa | jq .source_toolframe_order"leaf_to_root""root_to_leaf"events[].sampling.primary_metric# Count records by type
grep -o '"type":"[^"]*"' profile.spaa | sort | uniq -c | sort -rnheaderdsoframethreadstacksample# For perf data (uses "period" metric)
grep '"type":"stack"' profile.spaa | \
jq -s 'sort_by(-.weights[] | select(.metric=="period") | .value) | .[0:10]'
# For DTrace data (uses "samples" metric)
grep '"type":"stack"' profile.spaa | \
jq -s 'sort_by(-.weights[] | select(.metric=="samples") | .value) | .[0:10]'grep '"type":"stack"' profile.spaa | \
jq -s '[.[] | select(.exclusive) | {frame: .exclusive.frame, value: (.exclusive.weights[] | select(.metric=="period") | .value)}] | group_by(.frame) | map({frame: .[0].frame, total: (map(.value) | add)}) | sort_by(-.total) | .[0:20]'# Get frame details for a specific ID
grep '"type":"frame"' profile.spaa | jq 'select(.id == 101)'# Find top allocation sites by bytes allocated
grep '"type":"stack"' profile.spaa | \
jq -s '[.[] | select(.weights[] | .metric == "alloc_bytes")] | sort_by(-.weights[] | select(.metric=="alloc_bytes") | .value) | .[0:10]'
# Find potential memory leaks (high live_bytes)
grep '"type":"stack"' profile.spaa | \
jq -s '[.[] | select(.weights[] | .metric == "live_bytes")] | sort_by(-.weights[] | select(.metric=="live_bytes") | .value) | .[0:10]'alloc_bytesalloc_countlive_byteslive_countpeak_bytes# Extract a stack and resolve its frames
STACK_FRAMES=$(grep '"type":"stack"' profile.spaa | head -1 | jq -r '.frames | @csv')
# Build a frame lookup table, then query it
grep '"type":"frame"' profile.spaa | jq -s 'INDEX(.id)' > /tmp/frames.json
echo $STACK_FRAMES | tr ',' '\n' | while read fid; do
jq --arg id "$fid" '.[$id] | "\(.func) (\(.srcline // "unknown"))"' /tmp/frames.json
donegrep '"type":"stack"' profile.spaa | jq 'select(.context.tid == 4511)'grep '"type":"stack"' profile.spaa | jq 'select(.context.event == "cycles")'# Kernel stacks
grep '"type":"stack"' profile.spaa | jq 'select(.stack_type == "kernel")'
# Or check frame kinds
grep '"type":"frame"' profile.spaa | jq 'select(.kind == "kernel")' | head -20# Check if raw samples are included
grep -c '"type":"sample"' profile.spaa
# Plot sample distribution over time
grep '"type":"sample"' profile.spaa | jq -s 'group_by(.timestamp | floor) | map({time: .[0].timestamp | floor, count: length})'periodsampleslive_bytesalloc_bytes