- Home
- Skills
- Code Review
- Performance Code Review
Performance Code Review
Review code for performance issues: O(n squared) loops, memory leaks, unnecessary renders, and slow queries.
The Problem
Performance bugs rarely trigger errors — they just make everything slower. A nested loop that works fine with 100 items crawls at 10,000. A React component re-renders 47 times per keystroke because a callback is recreated every render. A database query fetches 50 related records one at a time instead of in a single join. These issues ship unnoticed until users complain or servers buckle under load.
The Prompt
Review the following code for performance issues. Act as a performance engineer profiling a production system under high load.
LANGUAGE/FRAMEWORK: [e.g., TypeScript/React, Python/Django, Rust]
EXPECTED SCALE: [e.g., 10k concurrent users, 1M database rows, mobile devices]
CODE:
[paste your code here]
Analyze across these performance dimensions:
1. **Algorithmic Complexity**
- Identify any O(n^2) or worse operations (nested loops, repeated array scans)
- Flag operations that should use a Set/Map for O(1) lookups instead of array.find/includes
- Check for redundant computation that could be cached/memoized
2. **Memory**
- Large object allocations inside loops or hot paths
- Missing cleanup (event listeners, intervals, subscriptions)
- Unbounded arrays/caches that grow without limits
3. **Rendering (Frontend)**
- Components re-rendering without prop changes
- Missing useMemo/useCallback for expensive computations or callback props
- Layout thrashing (reading DOM → writing DOM → reading DOM)
4. **I/O and Network**
- N+1 query patterns (fetching related data in loops)
- Missing pagination on list endpoints
- Sequential awaits that could be Promise.all
- Missing request deduplication or caching
5. **Bundle and Loading**
- Large imports that could be lazy-loaded
- Synchronous operations blocking the main thread
- Missing code splitting opportunities
For each issue, provide:
- **Location**: File and line
- **Impact**: Quantified estimate (e.g., "47 re-renders per keystroke", "O(n^2) with n=users")
- **Severity**: critical / moderate / minor
- **Fix**: Optimized code replacement
- **Tradeoff**: Any readability or complexity cost of the optimization
Example Output
## Performance Review: 5 issues found
### Critical: N+1 Query Pattern
Location: src/api/orders.ts:23
Impact: 1 query per order item. With 200 orders × 5 items = 1,000 queries instead of 2.
Code:
for (const order of orders) {
order.items = await db.query("SELECT * FROM items WHERE order_id = ?", [order.id]);
}
Fix:
const orderIds = orders.map(o => o.id);
const items = await db.query("SELECT * FROM items WHERE order_id IN (?)", [orderIds]);
// Group by order_id in application code
Tradeoff: Slightly more memory to hold all items at once. Negligible at this scale.
### Moderate: Unnecessary Re-renders
Location: src/components/SearchResults.tsx:15
Impact: Every keystroke re-renders all 50 result cards because filter function is recreated.
Fix: Wrap with useMemo:
const filtered = useMemo(() => results.filter(r => r.name.includes(query)), [results, query]);
When to Use
Run this before deploying features that handle lists, user-generated content, or database queries at scale. Especially valuable when moving from prototype (100 records) to production (100,000 records) — the performance patterns that work at small scale often collapse at real scale.
Pro Tips
- Specify your scale — “1,000 users” and “1,000,000 users” demand completely different optimization strategies. Always include expected data volume.
- Ask for Big-O annotations — request “Annotate each function with its time and space complexity” to get a complexity map of your code.
- Profile first, optimize second — use this review to identify suspects, then confirm with real profiling data before rewriting.