Advanced Debugging & Refactoring
Performance Optimization with AI Analysis
5 min read
The Performance Analysis Process
AI assistants can analyze performance from multiple angles:
- Code-level inefficiencies
- Database query optimization
- Network and I/O bottlenecks
- Frontend rendering issues
Code-Level Performance Analysis
Algorithmic Complexity Review
claude "Review this function for performance issues.
Identify algorithmic complexity and suggest optimizations.
[paste function]"
AI identifies issues:
// ORIGINAL: O(n²) complexity
function findDuplicates(items: Item[]): Item[] {
const duplicates: Item[] = [];
for (let i = 0; i < items.length; i++) {
for (let j = i + 1; j < items.length; j++) {
if (items[i].id === items[j].id) {
duplicates.push(items[i]);
}
}
}
return duplicates;
}
// OPTIMIZED: O(n) complexity
function findDuplicates(items: Item[]): Item[] {
const seen = new Map<string, Item>();
const duplicates: Item[] = [];
for (const item of items) {
if (seen.has(item.id)) {
duplicates.push(item);
} else {
seen.set(item.id, item);
}
}
return duplicates;
}
// Performance improvement: 100x faster for 1000 items
// Before: ~500ms | After: ~5ms
Bundle Size Analysis
claude "Analyze our bundle for size issues.
Here's the webpack-bundle-analyzer output.
Suggest code-splitting opportunities and heavy dependencies
that could be replaced."
## Bundle Analysis
### Current State
- Total bundle: 2.4 MB (gzipped: 680 KB)
- Largest chunks:
1. vendor.js: 1.2 MB (moment.js: 400 KB!)
2. main.js: 800 KB
3. charts.js: 400 KB
### Recommendations
1. **Replace moment.js with date-fns**
- Savings: 350 KB
- Tree-shakeable
- Same functionality
2. **Lazy load charts module**
```typescript
// Before
import { Charts } from './charts';
// After
const Charts = lazy(() => import('./charts'));
- Initial load savings: 400 KB
- Remove unused lodash functions
- Currently importing all of lodash
- Switch to lodash-es with tree shaking
- Savings: ~200 KB
Projected Results
- Total bundle: 1.4 MB (gzipped: 380 KB)
- 42% reduction in bundle size
- Estimated 1.2s faster initial load on 3G
## Database Query Optimization
### N+1 Query Detection
```bash
claude "Analyze this code for N+1 query problems.
[paste data fetching code]"
// PROBLEM: N+1 Query
async function getOrdersWithItems(userId: string) {
const orders = await prisma.order.findMany({
where: { userId }
});
// N additional queries!
for (const order of orders) {
order.items = await prisma.orderItem.findMany({
where: { orderId: order.id }
});
}
return orders;
}
// SOLUTION: Single query with include
async function getOrdersWithItems(userId: string) {
return prisma.order.findMany({
where: { userId },
include: {
items: {
include: {
product: true // Also include product details
}
}
}
});
}
// Performance: 50 queries → 1 query
// Response time: 450ms → 35ms
Query Plan Analysis
claude "Explain this PostgreSQL query plan and suggest
indexes to improve performance.
[paste EXPLAIN ANALYZE output]"
-- Original query (2.3s)
SELECT * FROM orders
JOIN order_items ON orders.id = order_items.order_id
WHERE orders.user_id = 'abc123'
AND orders.created_at > '2025-01-01';
-- Analysis:
-- Sequential scan on orders (1.2M rows)
-- No index on user_id or created_at
-- Recommended indexes:
CREATE INDEX idx_orders_user_id ON orders(user_id);
CREATE INDEX idx_orders_created_at ON orders(created_at);
-- Or composite:
CREATE INDEX idx_orders_user_created ON orders(user_id, created_at);
-- After indexing: 45ms (50x improvement)
Frontend Performance
React Render Optimization
claude "This component re-renders too often.
Analyze the render behavior and suggest optimizations.
[paste component code]"
// PROBLEM: Unnecessary re-renders
function OrderList({ orders, onSelect }) {
// New function created every render
const handleClick = (id) => () => onSelect(id);
// New array created every render
const sortedOrders = orders.sort((a, b) =>
b.date.getTime() - a.date.getTime()
);
return (
<div>
{sortedOrders.map(order => (
<OrderCard
key={order.id}
order={order}
onClick={handleClick(order.id)} // New function per item!
/>
))}
</div>
);
}
// OPTIMIZED
const OrderList = memo(function OrderList({ orders, onSelect }) {
// Memoize callback
const handleClick = useCallback((id: string) => {
onSelect(id);
}, [onSelect]);
// Memoize sorted orders
const sortedOrders = useMemo(() =>
[...orders].sort((a, b) => b.date.getTime() - a.date.getTime()),
[orders]
);
return (
<div>
{sortedOrders.map(order => (
<OrderCard
key={order.id}
order={order}
onSelect={handleClick} // Stable reference
/>
))}
</div>
);
});
// Child component also memoized
const OrderCard = memo(function OrderCard({ order, onSelect }) {
return (
<div onClick={() => onSelect(order.id)}>
{order.name}
</div>
);
});
Core Web Vitals Analysis
claude "Our Lighthouse score dropped to 65.
Analyze these metrics and provide specific fixes:
LCP: 4.2s (should be <2.5s)
FID: 180ms (should be <100ms)
CLS: 0.25 (should be <0.1)"
## Core Web Vitals Fix Plan
### LCP (4.2s → <2.5s)
**Issue**: Large hero image not optimized
**Fixes**:
1. Use next/image with priority for above-fold images
2. Add preload hint: `<link rel="preload" as="image">`
3. Serve WebP with fallback
4. Implement blur placeholder
### FID (180ms → <100ms)
**Issue**: Heavy JavaScript blocking main thread
**Fixes**:
1. Code-split non-critical JavaScript
2. Defer analytics and chat widgets
3. Use web workers for data processing
4. Break up long tasks with `scheduler.yield()`
### CLS (0.25 → <0.1)
**Issue**: Images and ads without dimensions
**Fixes**:
1. Add width/height to all images
2. Reserve space for dynamic content
3. Use CSS aspect-ratio for responsive images
4. Preload fonts to avoid FOIT/FOUT
### Implementation Priority
1. Image optimization (biggest LCP impact)
2. Script deferral (FID + LCP improvement)
3. Layout stabilization (CLS fix)
API Performance
Response Time Analysis
claude "Our API p95 latency is 2.3s. Analyze the request
flow and identify where time is being spent."
## Request Time Breakdown
Endpoint: POST /api/orders
| Stage | Time | % Total | Issue |
|-------|------|---------|-------|
| Auth middleware | 15ms | 0.7% | OK |
| Request parsing | 5ms | 0.2% | OK |
| Inventory check | 850ms | 37% | N+1 queries |
| Payment processing | 400ms | 17% | External API |
| Order creation | 200ms | 9% | OK |
| Email queueing | 750ms | 33% | Synchronous! |
| Response serialization | 80ms | 3% | Large payload |
### Optimizations
1. **Inventory Check (850ms → 50ms)**
- Batch product queries
- Add Redis cache for stock levels
2. **Email Queueing (750ms → 5ms)**
- Move to background job queue
- Don't wait for email service response
3. **Response Serialization (80ms → 20ms)**
- Return only necessary fields
- Use projection in database query
### Projected Result
- Current: 2300ms p95
- After: 680ms p95 (70% improvement)
Creating Performance Budgets
claude "Create a performance budget for our e-commerce app
based on competitor analysis and user expectations."
# .performance-budget.yaml
metrics:
# Core Web Vitals
LCP: 2000ms
FID: 100ms
CLS: 0.1
# Bundle sizes
javascript:
initial: 200KB
total: 500KB
css:
initial: 50KB
total: 100KB
# API response times
api:
p50: 200ms
p95: 500ms
p99: 1000ms
# Page-specific
pages:
home:
firstContentfulPaint: 1200ms
timeToInteractive: 2500ms
product:
firstContentfulPaint: 1000ms
timeToInteractive: 2000ms
checkout:
timeToInteractive: 1500ms
alerts:
slack: "#performance"
threshold: 10% # Alert if budget exceeded by 10%
Next Lesson
We'll cover large-scale refactoring techniques—how to safely transform codebases with AI assistance. :::