You are viewing v1 of 1. Go to the current version · All versions

Interpret profiling and benchmark output

Paste a profile, flame graph summary or timings and get a ranked list of real bottlenecks with what to try first.

Change note: Initial version

Prompt

Help me interpret performance data for a {{language}} program.

What the program does and what is slow: {{symptom}}
Environment (hardware, runtime version, load): {{environment}}
Profiler or tool used: {{tool}}

Profile or benchmark output:
{{data}}

Relevant code (optional):
{{code}}

Please:
1. Read the data: in two or three sentences describe where the time or memory goes, quoting the specific functions and numbers.
2. Separate signal from noise: say which entries are expected, which are profiler artifacts, and which are real bottlenecks. Consider self time versus total time.
3. Hypotheses: for each of the top three bottlenecks, say why it is probably slow (algorithmic complexity, allocation, I/O wait, lock contention, N+1 calls, GC pressure) and what evidence supports it.
4. Experiments: for each hypothesis, a small change to try and how to measure its effect, so I can confirm before committing to a rewrite.
5. Estimate the best case: what total improvement is realistic, using Amdahl's law with the numbers above.
6. What data is missing, and the exact command or setting to capture it.

Do not recommend micro-optimizations in code that is under 5% of the total. If the data is not enough to conclude, say so.

Variables

  • {{language}}Languageselect

    Options: TypeScript, JavaScript, Python, Go, Java, C#, Rust, Ruby, PHP, Kotlin, Swift, C++

    Default: Python

  • {{symptom}}Symptomtext

    Default: Nightly CSV import takes 40 minutes; it used to take 8

  • {{environment}}Environmenttext

    Default: Python 3.12, 4 vCPU container, 8 GB RAM, 2M rows

  • {{tool}}Tooltext

    Default: cProfile sorted by cumulative time

  • {{data}}Profile outputlongrequired

    Paste the top 20-40 lines of the report.

  • {{code}}Relevant codelong

Example output

**Where the time goes:** 31 of 40 minutes (78%) is inside `normalize_row`, and 24 minutes of that is `re.compile`, called 2M times. A further 6 minutes (15%) is `session.commit`, called once per row.

**Signal vs noise:** `csv.reader` (4%) and `json.dumps` (2%) are expected and not worth touching. Time in `<built-in method time.sleep>` is the retry backoff and is zero on a clean run.

**Hypotheses**
1. Regex recompiled per call. The cache is small, and `normalize_row` builds the pattern from a variable, defeating it. Try: compile once at module level.
2. Commit per row. 2M round trips. Try: commit every 5,000 rows.
3. N+1 lookup of the country table (`get_country`, 2M calls, 3% self time but 11% cumulative). Try: load the table into a dict once.

**Best case:** removing items 1 and 2 leaves about 3 minutes of work, so roughly 40 down to 9-10 minutes.

**Missing data:** memory use. Run `python -X tracemalloc` or `memray` to check batching will fit.

Notes

Separating self time from total time and asking for experiments before rewrites prevents optimizing the wrong thing. The Amdahl estimate shows how much win to expect.

Interpret profiling and benchmark output (v1) | LazyPrompt