Performance Optimization
Overview
Measure first, optimize second. Never optimize without data.
The bottleneck is almost never where you think it is.
When to Use
- Code is measurably slow or resource-heavy
- Profiling has revealed specific bottlenecks
- Designing a system with known performance requirements
- Reviewing code for performance before production
When NOT to Use
- You "feel like" code might be slow but haven't measured
- Premature optimization during initial implementation
- Micro-optimizations that don't move the needle
The Process
1. Measure baseline
Before touching anything, establish a benchmark.
- Record current performance numbers (time, memory, CPU)
- Document the test conditions (data size, concurrency, hardware)
- Save results as your baseline
2. Profile to find the bottleneck
Use profiling tools appropriate to your stack:
- Python:
cProfile, py-spy, memory_profiler
- Node.js:
--prof, clinic.js, Chrome DevTools
- Go:
pprof
- Generic: timing instrumentation, APM tools
The bottleneck is the one place where optimization actually matters.
3. Form hypothesis
State explicitly: "I believe X is slow because Y."
Don't optimize something you can't explain.
4. Apply targeted fix
Change ONE thing at a time.
Common high-impact areas:
- Database: N+1 queries, missing indexes, over-fetching
- Network: unnecessary round trips, large payloads, no caching
- Memory: leaks, excessive allocation, large objects in hot paths
- Algorithms: O(n²) where O(n log n) is possible
- I/O: synchronous blocking, missing batching
5. Measure again
Compare to baseline. Did it improve?
If not, revert and try something else.
6. Document the change
Record what you changed, why, and the before/after numbers.
Common High-Impact Wins
| Area |
Look For |
| Database |
N+1 queries, full table scans, missing indexes |
| Caching |
Repeated expensive computations with same inputs |
| Network |
Chatty APIs, large payloads, synchronous chains |
| Algorithms |
Nested loops over large collections |
| Memory |
Objects created in tight loops, large in-memory datasets |
Red Flags
| Thought |
Reality |
| "This looks slow" |
Measure it. Looks are deceiving. |
| "I'll optimize as I go" |
Premature optimization obscures intent. Measure first. |
| "I fixed the bottleneck" |
Did you measure? Fix without measurement isn't a fix. |
| "This is the obvious bottleneck" |
Profile anyway. You're probably wrong. |
1---2name: performance-optimization3description: Use when code is slow, resource-heavy, or needs optimization — before making any changes, after profiling reveals bottlenecks, or when designing performance-sensitive systems4---56# Performance Optimization78## Overview910Measure first, optimize second. Never optimize without data.11The bottleneck is almost never where you think it is.1213## When to Use1415- Code is measurably slow or resource-heavy16- Profiling has revealed specific bottlenecks17- Designing a system with known performance requirements18- Reviewing code for performance before production1920## When NOT to Use2122- You "feel like" code might be slow but haven't measured23- Premature optimization during initial implementation24- Micro-optimizations that don't move the needle2526## The Process2728**1. Measure baseline**29Before touching anything, establish a benchmark.30- Record current performance numbers (time, memory, CPU)31- Document the test conditions (data size, concurrency, hardware)32- Save results as your baseline3334**2. Profile to find the bottleneck**35Use profiling tools appropriate to your stack:36- Python: `cProfile`, `py-spy`, `memory_profiler`37- Node.js: `--prof`, `clinic.js`, Chrome DevTools38- Go: `pprof`39- Generic: timing instrumentation, APM tools4041The bottleneck is the one place where optimization actually matters.4243**3. Form hypothesis**44State explicitly: "I believe X is slow because Y."45Don't optimize something you can't explain.4647**4. Apply targeted fix**48Change ONE thing at a time.49Common high-impact areas:50- Database: N+1 queries, missing indexes, over-fetching51- Network: unnecessary round trips, large payloads, no caching52- Memory: leaks, excessive allocation, large objects in hot paths53- Algorithms: O(n²) where O(n log n) is possible54- I/O: synchronous blocking, missing batching5556**5. Measure again**57Compare to baseline. Did it improve?58If not, revert and try something else.5960**6. Document the change**61Record what you changed, why, and the before/after numbers.6263## Common High-Impact Wins6465| Area | Look For |66|------|----------|67| Database | N+1 queries, full table scans, missing indexes |68| Caching | Repeated expensive computations with same inputs |69| Network | Chatty APIs, large payloads, synchronous chains |70| Algorithms | Nested loops over large collections |71| Memory | Objects created in tight loops, large in-memory datasets |7273## Red Flags7475| Thought | Reality |76|---------|---------|77| "This looks slow" | Measure it. Looks are deceiving. |78| "I'll optimize as I go" | Premature optimization obscures intent. Measure first. |79| "I fixed the bottleneck" | Did you measure? Fix without measurement isn't a fix. |80| "This is the obvious bottleneck" | Profile anyway. You're probably wrong. |