Performance Optimization Skill
When analyzing code for performance, follow this structured process:
1. Understand What's Slow
- Ask or determine: what operation is slow? (page load, API response, build time, query, render)
- What's the current performance? (response time, load time, memory usage)
- What's the expected/acceptable performance?
- How much data is involved? (10 rows vs 10 million rows changes everything)
2. Algorithm & Data Structure Analysis
- Identify time complexity of key operations (O(n), O(n²), O(n log n), etc.)
- Look for nested loops over large datasets
- Check if a different data structure would help:
- Array lookups that should be Map/Set/Object for O(1) access
- Linear searches that should use binary search or indexing
- Repeated array filtering that should be pre-grouped
- Look for unnecessary sorting or repeated work
Flag pattern:
// 🔴 BAD — O(n²): nested loop for lookups
users.forEach(user => {
const order = orders.find(o => o.userId === user.id);
});
// ✅ GOOD — O(n): pre-index with Map
const orderMap = new Map(orders.map(o => [o.userId, o]));
users.forEach(user => {
const order = orderMap.get(user.id);
});
3. Database & Query Performance
- N+1 queries: Loading related data inside a loop instead of batch loading
- Missing indexes: Queries filtering/sorting on unindexed columns
- Over-fetching: SELECT * when only a few columns are needed
- Missing pagination: Loading entire tables into memory
- Unoptimized joins: Joining large tables without proper conditions
- Missing connection pooling: Opening new connections per request
Flag pattern:
// 🔴 BAD — N+1: one query per user
for (const user of users) {
const posts = await db.query('SELECT * FROM posts WHERE user_id = ?', [user.id]);
}
// ✅ GOOD — single batch query
const posts = await db.query('SELECT * FROM posts WHERE user_id IN (?)', [userIds]);
const postsByUser = groupBy(posts, 'user_id');
4. Memory Analysis
- Memory leaks: Event listeners not cleaned up, intervals not cleared, subscriptions not unsubscribed
- Large object retention: Holding references to data no longer needed
- Unbounded caches: Caches that grow forever without eviction
- String concatenation in loops: Use array join or StringBuilder instead
- Loading entire files into memory: Stream large files instead
Flag pattern:
// 🔴 BAD — memory leak: listener never removed
useEffect(() => {
window.addEventListener('resize', handleResize);
}, []);
// ✅ GOOD — cleanup on unmount
useEffect(() => {
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
5. Frontend Performance (if applicable)
- Unnecessary re-renders: Missing React.memo, useMemo, useCallback
- Large bundle size: Importing entire libraries when only one function is needed
- Missing code splitting: Large pages that should be lazy loaded
- Unoptimized images: Missing compression, wrong format, no lazy loading
- Layout thrashing: Reading and writing DOM properties in a loop
- Missing virtualization: Rendering thousands of list items instead of virtualizing
- Blocking main thread: Heavy computation not offloaded to Web Worker
Flag pattern:
// 🔴 BAD — re-computes on every render
const sorted = items.sort((a, b) => a.name.localeCompare(b.name));
// ✅ GOOD — memoized
const sorted = useMemo(
() => [...items].sort((a, b) => a.name.localeCompare(b.name)),
[items]
);
6. API & Network Performance
- Missing caching: Responses that could be cached (HTTP headers, Redis, in-memory)
- No request batching: Multiple small requests that could be combined
- Missing compression: Large JSON responses without gzip/brotli
- Synchronous operations: Blocking calls that could be parallelized
- No pagination: Returning unbounded result sets
- Missing timeouts: External calls without timeout limits
Flag pattern:
// 🔴 BAD — sequential when independent
const users = await fetchUsers();
const products = await fetchProducts();
const orders = await fetchOrders();
// ✅ GOOD — parallel execution
const [users, products, orders] = await Promise.all([
fetchUsers(),
fetchProducts(),
fetchOrders(),
]);
7. Concurrency & Async
- Uncontrolled parallelism: Firing 10,000 requests at once instead of batching
- Missing debounce/throttle: Search inputs firing on every keystroke
- Blocking event loop: CPU-heavy sync operations in Node.js
- Missing queue: Tasks that should be queued and processed in background
8. Build & Tooling (if applicable)
- Slow builds from unnecessary transpilation
- Missing tree shaking
- Duplicated dependencies in bundle
- Missing caching in CI/CD pipeline
Output Format
For each issue found:
[IMPACT] Category — File:Line
- Problem: What's slow and why
- Current complexity: O(?) or estimated impact
- Suggested fix: How to improve it
- Expected improvement: What performance gain to expect
// before (slow)
...
// after (fast)
...
Impact levels:
- 🔴 HIGH — Causes noticeable slowdown or crashes at scale. Fix first.
- 🟡 MEDIUM — Degrades performance under load. Fix soon.
- 🟢 LOW — Minor inefficiency. Optimize when convenient.
Summary
End every analysis with:
- Biggest bottleneck — The single highest-impact issue
- Quick wins — Changes that take <30 minutes and give noticeable improvement
- Estimated improvement — What overall performance gain to expect after fixes
- Measurement plan — How to verify the improvements (specific metrics to track, tools to use)
1---2name: optimize3description: Analyzes code for performance issues including slow algorithms, memory leaks, unnecessary re-renders, database query problems, and resource bottlenecks. Use when the user says "this is slow", "optimize this", "performance issue", "why is this taking so long?", or "make this faster".4---56# Performance Optimization Skill78When analyzing code for performance, follow this structured process:910## 1. Understand What's Slow11- Ask or determine: what operation is slow? (page load, API response, build time, query, render)12- What's the current performance? (response time, load time, memory usage)13- What's the expected/acceptable performance?14- How much data is involved? (10 rows vs 10 million rows changes everything)1516## 2. Algorithm & Data Structure Analysis17- Identify time complexity of key operations (O(n), O(n²), O(n log n), etc.)18- Look for nested loops over large datasets19- Check if a different data structure would help:20 - Array lookups that should be Map/Set/Object for O(1) access21 - Linear searches that should use binary search or indexing22 - Repeated array filtering that should be pre-grouped23- Look for unnecessary sorting or repeated work2425Flag pattern:26```27// 🔴 BAD — O(n²): nested loop for lookups28users.forEach(user => {29 const order = orders.find(o => o.userId === user.id);30});3132// ✅ GOOD — O(n): pre-index with Map33const orderMap = new Map(orders.map(o => [o.userId, o]));34users.forEach(user => {35 const order = orderMap.get(user.id);36});37```3839## 3. Database & Query Performance40- **N+1 queries**: Loading related data inside a loop instead of batch loading41- **Missing indexes**: Queries filtering/sorting on unindexed columns42- **Over-fetching**: SELECT * when only a few columns are needed43- **Missing pagination**: Loading entire tables into memory44- **Unoptimized joins**: Joining large tables without proper conditions45- **Missing connection pooling**: Opening new connections per request4647Flag pattern:48```49// 🔴 BAD — N+1: one query per user50for (const user of users) {51 const posts = await db.query('SELECT * FROM posts WHERE user_id = ?', [user.id]);52}5354// ✅ GOOD — single batch query55const posts = await db.query('SELECT * FROM posts WHERE user_id IN (?)', [userIds]);56const postsByUser = groupBy(posts, 'user_id');57```5859## 4. Memory Analysis60- **Memory leaks**: Event listeners not cleaned up, intervals not cleared, subscriptions not unsubscribed61- **Large object retention**: Holding references to data no longer needed62- **Unbounded caches**: Caches that grow forever without eviction63- **String concatenation in loops**: Use array join or StringBuilder instead64- **Loading entire files into memory**: Stream large files instead6566Flag pattern:67```68// 🔴 BAD — memory leak: listener never removed69useEffect(() => {70 window.addEventListener('resize', handleResize);71}, []);7273// ✅ GOOD — cleanup on unmount74useEffect(() => {75 window.addEventListener('resize', handleResize);76 return () => window.removeEventListener('resize', handleResize);77}, []);78```7980## 5. Frontend Performance (if applicable)81- **Unnecessary re-renders**: Missing React.memo, useMemo, useCallback82- **Large bundle size**: Importing entire libraries when only one function is needed83- **Missing code splitting**: Large pages that should be lazy loaded84- **Unoptimized images**: Missing compression, wrong format, no lazy loading85- **Layout thrashing**: Reading and writing DOM properties in a loop86- **Missing virtualization**: Rendering thousands of list items instead of virtualizing87- **Blocking main thread**: Heavy computation not offloaded to Web Worker8889Flag pattern:90```91// 🔴 BAD — re-computes on every render92const sorted = items.sort((a, b) => a.name.localeCompare(b.name));9394// ✅ GOOD — memoized95const sorted = useMemo(96 () => [...items].sort((a, b) => a.name.localeCompare(b.name)),97 [items]98);99```100101## 6. API & Network Performance102- **Missing caching**: Responses that could be cached (HTTP headers, Redis, in-memory)103- **No request batching**: Multiple small requests that could be combined104- **Missing compression**: Large JSON responses without gzip/brotli105- **Synchronous operations**: Blocking calls that could be parallelized106- **No pagination**: Returning unbounded result sets107- **Missing timeouts**: External calls without timeout limits108109Flag pattern:110```111// 🔴 BAD — sequential when independent112const users = await fetchUsers();113const products = await fetchProducts();114const orders = await fetchOrders();115116// ✅ GOOD — parallel execution117const [users, products, orders] = await Promise.all([118 fetchUsers(),119 fetchProducts(),120 fetchOrders(),121]);122```123124## 7. Concurrency & Async125- **Uncontrolled parallelism**: Firing 10,000 requests at once instead of batching126- **Missing debounce/throttle**: Search inputs firing on every keystroke127- **Blocking event loop**: CPU-heavy sync operations in Node.js128- **Missing queue**: Tasks that should be queued and processed in background129130## 8. Build & Tooling (if applicable)131- Slow builds from unnecessary transpilation132- Missing tree shaking133- Duplicated dependencies in bundle134- Missing caching in CI/CD pipeline135136## Output Format137138For each issue found:139140**[IMPACT] Category — File:Line**141- **Problem**: What's slow and why142- **Current complexity**: O(?) or estimated impact143- **Suggested fix**: How to improve it144- **Expected improvement**: What performance gain to expect145```146// before (slow)147...148149// after (fast)150...151```152153Impact levels:154- 🔴 **HIGH** — Causes noticeable slowdown or crashes at scale. Fix first.155- 🟡 **MEDIUM** — Degrades performance under load. Fix soon.156- 🟢 **LOW** — Minor inefficiency. Optimize when convenient.157158## Summary159160End every analysis with:1611. **Biggest bottleneck** — The single highest-impact issue1622. **Quick wins** — Changes that take <30 minutes and give noticeable improvement1633. **Estimated improvement** — What overall performance gain to expect after fixes1644. **Measurement plan** — How to verify the improvements (specific metrics to track, tools to use)