---
name: lisa-performance-review
description: "Performance review methodology"
---

# Performance Review

Identify bottlenecks, inefficiencies, and scalability risks in code changes.

## Analysis Process

1. **Read affected files** -- understand data access patterns, algorithmic complexity, and resource usage
2. **Identify N+1 queries** -- look for ORM calls inside loops, missing eager loading, unbatched database access
3. **Check algorithmic complexity** -- nested loops over collections, repeated linear scans, unnecessary sorting
4. **Evaluate memory usage** -- large object allocations, unbounded caches, retained references, memory leaks
5. **Review database patterns** -- missing indexes, full table scans, unoptimized joins, excessive round trips
6. **Check caching** -- missing cache layers, cache invalidation issues, redundant computations
7. **Assess bundle/payload size** -- unnecessary imports, large dependencies, uncompressed responses
8. **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
```typescript
// Bad: N+1 -- one query per user inside loop
const users = await userRepo.find();
const profiles = await Promise.all(users.map(u => profileRepo.findOne({ userId: u.id })));

// Good: Single query with join or batch
const users = await userRepo.find({ relations: ["profile"] });
```

### Unnecessary Re-computation
```typescript
// Bad: Recomputes on every call
const getExpensiveResult = () => heavyComputation(data);

// Good: Compute once, reuse
const expensiveResult = heavyComputation(data);
```

### Unbounded Collection Growth
```typescript
// Bad: Cache grows without limit
const cache = new Map();
const get = (key) => { if (!cache.has(key)) cache.set(key, compute(key)); return cache.get(key); };

// Good: LRU or bounded cache
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
