Profiler flame graphs and EXPLAIN ANALYZE plans are dense artifacts that most engineers read slowly and occasionally misread.
Tier: Core · Workflow area: Debugging & Performance
An AI assistant is excellent at the translation step — converting raw profiler/planner output into ranked bottleneck hypotheses — as long as you keep the confirmation step deterministic: every hypothesis earns a benchmark before it earns a fix.
Do not use AI to guess at bottlenecks without evidence — models pattern-match to popular causes (N+1, missing index) and will confidently confirm your bias.
py-spy/cProfile (Python), pprof (Go), async-profiler/JFR (JVM), clinic/0x (Node).EXPLAIN (ANALYZE, BUFFERS) in Postgres or EXPLAIN ANALYZE in MySQL 8+.hey, wrk, pytest-benchmark, JMH, or a k6 script.Capture evidence under realistic load. Examples:
# Python: 60s sampling profile of the running service, flame graph + top functions
py-spy record -d 60 -p <PID> -o profile.svg
py-spy dump --pid <PID>
# Postgres: actual (not estimated) plan with buffer stats
EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT) SELECT ... ;
Capture at production-like data volume — a plan over 1,000 rows is a different plan than over 50 million.
Ask for ranked hypotheses, not fixes. Paste the artifact with:
Below is [a py-spy top output / an EXPLAIN ANALYZE plan] from a service whose
p95 went from 180ms to 900ms after [context: data growth, deploy, traffic].
1. Interpret the artifact: where does actual time go? Quote the specific
lines/nodes (function %, node actual time, rows expected vs actual, buffer
reads) that support each claim.
2. Rank the top 3 bottleneck hypotheses by expected impact.
3. For each: what single cheap measurement would confirm or kill it?
Do NOT propose code or index changes yet.
Requiring quoted evidence per claim is what separates interpretation from confabulation — a hypothesis that cannot cite a plan node is a guess.
Check the classic misread sites yourself. In query plans: rows estimated vs actual mismatches (stale statistics), Rows Removed by Filter (index not selective), buffer reads vs hits (cold cache vs genuine I/O), and whether a nested-loop node's actual time multiplies by loop count. Ask the model to walk each of these explicitly if its summary skipped them.
Confirm the top hypothesis with a micro-benchmark before fixing. Have the assistant generate the harness:
Hypothesis 1 is the ORDER BY ... LIMIT sort spilling to disk (Sort Method:
external merge, Disk: 210MB). Generate a benchmark script that runs this
query 20 times with warm cache against $DATABASE_URL, records p50/p95, and
prints the sort method used. I will run it before and after any change.
Run it. If the confirming measurement does not move, kill the hypothesis and promote the next one — do not fix anyway.
Apply the fix, re-run the same harness, keep the receipts. Paste before/after numbers back into the thread and ask for a plain-language summary for the PR description. A perf PR without before/after numbers from an identical harness is an opinion.
Feed the model the raw artifact, not your summary of it. The value is a second reader of the evidence; if you pre-digest it, you transfer your misreadings.
EXPLAIN (ANALYZE, BUFFERS) plans and multi-hundred-line pprof text dumps pasted whole.profile the test suite, then rerun after the change) — keep the before/after comparison in your hands.ANALYZE was run if statistics were stale).Rows Removed by Filter: 12 fixes nothing.t1/c1 consistently (keep the mapping local) — plan structure is what the model needs, not names.WHERE email = $1, never the actual email) — DPDP-relevant personal data hides in query literals and log lines.