| name | performance-review |
| description | Performance review methodology. N+1 queries, inefficient algorithms, memory leaks, missing indexes, unnecessary re-renders, bundle size issues. Evidence-based recommendations. |
Performance Review
Identify bottlenecks, inefficiencies, and scalability risks in code changes.
Analysis Process
- Read affected files -- understand data access patterns, algorithmic complexity, and resource usage
- Identify N+1 queries -- look for ORM calls inside loops, missing eager loading, unbatched database access
- Check algorithmic complexity -- nested loops over collections, repeated linear scans, unnecessary sorting
- Evaluate memory usage -- large object allocations, unbounded caches, retained references, memory leaks
- Review database patterns -- missing indexes, full table scans, unoptimized joins, excessive round trips
- Check caching -- missing cache layers, cache invalidation issues, redundant computations
- Assess bundle/payload size -- unnecessary imports, large dependencies, uncompressed responses
- Review rendering performance -- unnecessary re-renders, missing memoization, layout thrashing (frontend)
Output Format
Structure findings as:
## Performance Analysis
### Critical Issues
Issues that will cause noticeable degradation at scale.
- [issue] -- where in the code, why it matters, estimated impact
### N+1 Query Detection
| Location | Pattern | Fix |
|----------|---------|-----|
| file:line | Description of the N+1 | Eager load / batch / join |
### Algorithmic Complexity
| Location | Current | Suggested | Why |
|----------|---------|-----------|-----|
| file:line | O(n^2) | O(n) | Description |
### Database Concerns
- Missing indexes, unoptimized queries, excessive round trips
### Memory Concerns
- Unbounded growth, large allocations, retained references
### Caching Opportunities
- Computations or queries that could benefit from caching
### Recommendations
- [recommendation] -- priority (critical/warning/suggestion), estimated impact
Common Patterns to Flag
N+1 Queries
const users = await userRepo.find();
const profiles = await Promise.all(users.map(u => profileRepo.findOne({ userId: u.id })));
const users = await userRepo.find({ relations: ["profile"] });
Unnecessary Re-computation
const getExpensiveResult = () => heavyComputation(data);
const expensiveResult = heavyComputation(data);
Unbounded Collection Growth
const cache = new Map();
const get = (key) => { if (!cache.has(key)) cache.set(key, compute(key)); return cache.get(key); };
const cache = new LRUCache({ max: 1000 });
Rules
- Focus on the specific changes proposed, not a full performance audit of the entire codebase
- Flag only real performance risks -- do not micro-optimize code that runs once at startup
- Quantify impact where possible (O(n) vs O(n^2), number of database round trips, estimated payload size)
- Distinguish between critical issues (will degrade at scale) and suggestions (marginal improvement)
- If the changes have no performance implications, report "No performance concerns" and explain why
- Always consider the data scale -- an O(n^2) over 5 items is fine, over 10,000 is not