Loading...
Loading...
Performance and scalability analysis specialist. Identifies algorithmic inefficiencies, N+1 queries, memory leaks, and concurrency issues. Use when reviewing loops, database queries, file I/O, or high-concurrency code.
npx skill4agent add xinbenlv/codereview-skills codereview-performance// 🚨 O(n²) - problematic if users/orders are large
users.forEach(user => {
orders.forEach(order => { ... })
})// 🚨 Three iterations when one would suffice
const filtered = items.filter(...)
const mapped = filtered.map(...)
const sorted = mapped.sort(...)
// ✅ Combined or use reduce// 🚨 Continues after finding result
let result;
items.forEach(item => { if (match) result = item; })
// ✅ Exits early
const result = items.find(item => match)// 🚨 N+1: 1 query for users, N queries for orders
const users = await getUsers()
for (const user of users) {
user.orders = await getOrdersForUser(user.id)
}
// ✅ Single query with JOIN or batch fetch
const users = await getUsersWithOrders()// 🚨 Listeners accumulate on each call
function setup() {
element.addEventListener('click', handler)
}
// ✅ Remove on cleanup
function cleanup() {
element.removeEventListener('click', handler)
}// 🚨 Loads entire file into memory
const content = fs.readFileSync(largeFile)
// ✅ Streams data
const stream = fs.createReadStream(largeFile)// 🚨 Connection leak
const conn = await pool.getConnection()
const result = await conn.query(...)
// connection never released
// ✅ Always release
try {
const conn = await pool.getConnection()
return await conn.query(...)
} finally {
conn.release()
}// 🚨 Race condition: read-modify-write
const count = await getCount()
await setCount(count + 1)
// ✅ Atomic operation
await incrementCount()// 🚨 May open 10,000 connections at once
await Promise.all(items.map(item => fetchData(item)))
// ✅ Batch or limit concurrency
await pMap(items, fetchData, { concurrency: 10 })// 🚨 Sequential execution (slow)
for (const item of items) {
await processItem(item)
}
// ✅ Parallel execution (if order doesn't matter)
await Promise.all(items.map(processItem))## Performance Analysis
### Critical Issues 🔴
| Issue | Location | Impact | Recommendation |
|-------|----------|--------|----------------|
| N+1 Query | `users.ts:42` | O(n) DB calls | Use eager loading |
| Unbounded loop | `process.ts:15` | O(n²) complexity | Add pagination |
### Warnings 🟡
| Issue | Location | Concern |
|-------|----------|---------|
| Large array in memory | `cache.ts:30` | May cause OOM at scale |
| No connection pooling | `db.ts:10` | Connection exhaustion |
### Optimization Opportunities 🟢
- `utils.ts:50`: Could use Map instead of repeated Array.find()
- `api.ts:25`: Responses could be gzip compressed
### Estimated Impact
| Metric | Current | After Fix |
|--------|---------|-----------|
| DB Queries per request | O(n) | O(1) |
| Memory usage | O(n) | O(1) |
| Response time | ~500ms | ~50ms |□ Algorithmic Complexity
□ No unnecessary O(n²)?
□ No redundant iterations?
□ Early exit when possible?
□ Optimal algorithm choice?
□ Database
□ No N+1 queries?
□ Proper indexing?
□ Bounded result sets?
□ Pagination for large data?
□ Memory
□ No memory leaks?
□ Streaming for large files?
□ Closures don't hold large objects?
□ Resource Cleanup
□ Connections released?
□ Files closed?
□ Listeners removed?
□ Timers cleared?
□ Concurrency
□ No race conditions?
□ No deadlocks?
□ Bounded parallelism?// Process in batches to avoid memory issues
async function processBatch(items, batchSize = 100) {
for (let i = 0; i < items.length; i += batchSize) {
const batch = items.slice(i, i + batchSize)
await Promise.all(batch.map(process))
}
}// Always release connections
async function withConnection(fn) {
const conn = await pool.getConnection()
try {
return await fn(conn)
} finally {
conn.release()
}
}// Prevent excessive calls
function debounce(fn, delay) {
let timeoutId
return (...args) => {
clearTimeout(timeoutId)
timeoutId = setTimeout(() => fn(...args), delay)
}
}