Initial commit
This commit is contained in:
65
skills/performance-optimization/reference/INDEX.md
Normal file
65
skills/performance-optimization/reference/INDEX.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# Performance Optimization Reference
|
||||
|
||||
Reference materials for performance metrics, profiling tools, and optimization patterns.
|
||||
|
||||
## Reference Materials
|
||||
|
||||
### Performance Metrics
|
||||
**File**: [performance-metrics.md](performance-metrics.md)
|
||||
|
||||
Complete guide to measuring and tracking performance:
|
||||
- Web Vitals (LCP, FID, CLS, TTFB)
|
||||
- Backend metrics (latency, throughput, error rate)
|
||||
- Database metrics (query time, connection pool)
|
||||
- Memory metrics (heap size, garbage collection)
|
||||
- Lighthouse scores and interpretation
|
||||
|
||||
**Use when**: Setting up monitoring, establishing performance budgets, tracking improvements.
|
||||
|
||||
---
|
||||
|
||||
### Profiling Tools
|
||||
**File**: [profiling-tools.md](profiling-tools.md)
|
||||
|
||||
Tools for identifying performance bottlenecks:
|
||||
- Chrome DevTools (Performance, Memory, Network panels)
|
||||
- Node.js profiling (--inspect, clinic.js, 0x)
|
||||
- React DevTools Profiler
|
||||
- Database query analyzers (EXPLAIN, pg_stat_statements)
|
||||
- APM tools (DataDog, New Relic, Sentry)
|
||||
|
||||
**Use when**: Investigating slow performance, finding bottlenecks, profiling before optimization.
|
||||
|
||||
---
|
||||
|
||||
### Optimization Patterns
|
||||
**File**: [optimization-patterns.md](optimization-patterns.md)
|
||||
|
||||
Catalog of common optimization patterns:
|
||||
- Algorithm patterns (Map lookup, binary search, memoization)
|
||||
- Database patterns (eager loading, indexing, caching)
|
||||
- Caching patterns (LRU, cache-aside, write-through)
|
||||
- Frontend patterns (lazy loading, code splitting, virtualization)
|
||||
- Backend patterns (pooling, batching, streaming)
|
||||
|
||||
**Use when**: Looking for proven solutions, learning optimization techniques.
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference
|
||||
|
||||
| Resource | Focus | Primary Use |
|
||||
|----------|-------|-------------|
|
||||
| **Performance Metrics** | Measurement | Tracking performance |
|
||||
| **Profiling Tools** | Analysis | Finding bottlenecks |
|
||||
| **Optimization Patterns** | Solutions | Implementing fixes |
|
||||
|
||||
## Navigation
|
||||
|
||||
- **Examples**: [Examples Index](../examples/INDEX.md)
|
||||
- **Templates**: [Templates Index](../templates/INDEX.md)
|
||||
- **Main Agent**: [performance-optimizer.md](../performance-optimizer.md)
|
||||
|
||||
---
|
||||
|
||||
Return to [main agent](../performance-optimizer.md)
|
||||
@@ -0,0 +1,150 @@
|
||||
# Optimization Patterns Catalog
|
||||
|
||||
Proven patterns for common performance bottlenecks.
|
||||
|
||||
## Algorithm Patterns
|
||||
|
||||
### 1. Map Lookup
|
||||
**Problem**: O(n²) nested loops
|
||||
**Solution**: O(n) with Map
|
||||
**Gain**: 100-1000x faster
|
||||
|
||||
```typescript
|
||||
// Before: O(n²)
|
||||
items.forEach(item => {
|
||||
const related = items.find(i => i.id === item.relatedId);
|
||||
});
|
||||
|
||||
// After: O(n)
|
||||
const map = new Map(items.map(i => [i.id, i]));
|
||||
items.forEach(item => {
|
||||
const related = map.get(item.relatedId);
|
||||
});
|
||||
```
|
||||
|
||||
### 2. Memoization
|
||||
**Problem**: Repeated expensive calculations
|
||||
**Solution**: Cache results
|
||||
**Gain**: 10-100x faster
|
||||
|
||||
```typescript
|
||||
const memo = new Map();
|
||||
function fibonacci(n) {
|
||||
if (n <= 1) return n;
|
||||
if (memo.has(n)) return memo.get(n);
|
||||
const result = fibonacci(n - 1) + fibonacci(n - 2);
|
||||
memo.set(n, result);
|
||||
return result;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Database Patterns
|
||||
|
||||
### 1. Eager Loading
|
||||
**Problem**: N+1 queries
|
||||
**Solution**: JOIN or include relations
|
||||
**Gain**: 10-100x fewer queries
|
||||
|
||||
```typescript
|
||||
// Before: N+1
|
||||
const users = await User.findAll();
|
||||
for (const user of users) {
|
||||
user.posts = await Post.findAll({ where: { userId: user.id } });
|
||||
}
|
||||
|
||||
// After: 1 query
|
||||
const users = await User.findAll({ include: ['posts'] });
|
||||
```
|
||||
|
||||
### 2. Composite Index
|
||||
**Problem**: Slow WHERE + ORDER BY
|
||||
**Solution**: Multi-column index
|
||||
**Gain**: 100-1000x faster
|
||||
|
||||
```sql
|
||||
CREATE INDEX idx_orders_customer_status_date
|
||||
ON orders(customer_id, status, created_at DESC);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Caching Patterns
|
||||
|
||||
### 1. Cache-Aside
|
||||
**Problem**: Database load
|
||||
**Solution**: Check cache, fallback to DB
|
||||
**Gain**: 5-50x faster
|
||||
|
||||
```typescript
|
||||
async function get(key) {
|
||||
let value = cache.get(key);
|
||||
if (!value) {
|
||||
value = await db.get(key);
|
||||
cache.set(key, value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Write-Through
|
||||
**Problem**: Cache staleness
|
||||
**Solution**: Write to cache and DB
|
||||
**Gain**: Always fresh cache
|
||||
|
||||
```typescript
|
||||
async function set(key, value) {
|
||||
await db.set(key, value);
|
||||
cache.set(key, value);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Frontend Patterns
|
||||
|
||||
### 1. Code Splitting
|
||||
**Problem**: Large bundle
|
||||
**Solution**: Dynamic imports
|
||||
**Gain**: 2-10x faster initial load
|
||||
|
||||
```typescript
|
||||
const Component = lazy(() => import('./Component'));
|
||||
```
|
||||
|
||||
### 2. Virtual Scrolling
|
||||
**Problem**: Large lists
|
||||
**Solution**: Render only visible items
|
||||
**Gain**: 10-100x less DOM
|
||||
|
||||
```typescript
|
||||
<FixedSizeList itemCount={10000} itemSize={50} height={600} />
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Backend Patterns
|
||||
|
||||
### 1. Connection Pooling
|
||||
**Problem**: Connection overhead
|
||||
**Solution**: Reuse connections
|
||||
**Gain**: 5-10x faster
|
||||
|
||||
```typescript
|
||||
const pool = new Pool({ max: 20 });
|
||||
```
|
||||
|
||||
### 2. Request Batching
|
||||
**Problem**: Too many small requests
|
||||
**Solution**: Batch multiple requests
|
||||
**Gain**: 10-100x fewer calls
|
||||
|
||||
```typescript
|
||||
const batch = users.map(u => u.id);
|
||||
const results = await api.getBatch(batch);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Previous**: [Profiling Tools](profiling-tools.md) | **Index**: [Reference Index](INDEX.md)
|
||||
212
skills/performance-optimization/reference/performance-metrics.md
Normal file
212
skills/performance-optimization/reference/performance-metrics.md
Normal file
@@ -0,0 +1,212 @@
|
||||
# Performance Metrics Reference
|
||||
|
||||
Comprehensive guide to measuring and tracking performance across web, backend, and database layers.
|
||||
|
||||
## Web Vitals (Core)
|
||||
|
||||
### Largest Contentful Paint (LCP)
|
||||
**Target**: <2.5s | **Poor**: >4.0s
|
||||
|
||||
Measures loading performance. Largest visible element in viewport.
|
||||
|
||||
```javascript
|
||||
// Measure LCP
|
||||
const observer = new PerformanceObserver((list) => {
|
||||
const entries = list.getEntries();
|
||||
const lastEntry = entries[entries.length - 1];
|
||||
console.log('LCP:', lastEntry.renderTime || lastEntry.loadTime);
|
||||
});
|
||||
observer.observe({ entryTypes: ['largest-contentful-paint'] });
|
||||
```
|
||||
|
||||
**Improvements**:
|
||||
- Optimize images (WebP, lazy loading)
|
||||
- Reduce server response time
|
||||
- Eliminate render-blocking resources
|
||||
- Use CDN for static assets
|
||||
|
||||
---
|
||||
|
||||
### First Input Delay (FID)
|
||||
**Target**: <100ms | **Poor**: >300ms
|
||||
|
||||
Measures interactivity. Time from user interaction to browser response.
|
||||
|
||||
```javascript
|
||||
// Measure FID
|
||||
const observer = new PerformanceObserver((list) => {
|
||||
const entries = list.getEntries();
|
||||
entries.forEach((entry) => {
|
||||
console.log('FID:', entry.processingStart - entry.startTime);
|
||||
});
|
||||
});
|
||||
observer.observe({ entryTypes: ['first-input'] });
|
||||
```
|
||||
|
||||
**Improvements**:
|
||||
- Split long tasks
|
||||
- Use web workers for heavy computation
|
||||
- Optimize JavaScript execution
|
||||
- Defer non-critical JavaScript
|
||||
|
||||
---
|
||||
|
||||
### Cumulative Layout Shift (CLS)
|
||||
**Target**: <0.1 | **Poor**: >0.25
|
||||
|
||||
Measures visual stability. Unexpected layout shifts.
|
||||
|
||||
```javascript
|
||||
// Measure CLS
|
||||
let clsScore = 0;
|
||||
const observer = new PerformanceObserver((list) => {
|
||||
list.getEntries().forEach((entry) => {
|
||||
if (!entry.hadRecentInput) {
|
||||
clsScore += entry.value;
|
||||
}
|
||||
});
|
||||
console.log('CLS:', clsScore);
|
||||
});
|
||||
observer.observe({ entryTypes: ['layout-shift'] });
|
||||
```
|
||||
|
||||
**Improvements**:
|
||||
- Set explicit dimensions for images/videos
|
||||
- Avoid inserting content above existing content
|
||||
- Use transform animations instead of layout properties
|
||||
- Reserve space for ads/embeds
|
||||
|
||||
---
|
||||
|
||||
## Backend Metrics
|
||||
|
||||
### Response Time (Latency)
|
||||
**Target**: p50 <100ms, p95 <200ms, p99 <500ms
|
||||
|
||||
```javascript
|
||||
// Track with middleware
|
||||
app.use((req, res, next) => {
|
||||
const start = Date.now();
|
||||
res.on('finish', () => {
|
||||
const duration = Date.now() - start;
|
||||
metrics.histogram('http.response_time', duration, {
|
||||
method: req.method,
|
||||
route: req.route?.path,
|
||||
status: res.statusCode
|
||||
});
|
||||
});
|
||||
next();
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Throughput
|
||||
**Target**: Varies by application (e.g., 1000 req/s)
|
||||
|
||||
```javascript
|
||||
let requestCount = 0;
|
||||
setInterval(() => {
|
||||
metrics.gauge('http.throughput', requestCount);
|
||||
requestCount = 0;
|
||||
}, 1000);
|
||||
|
||||
app.use((req, res, next) => {
|
||||
requestCount++;
|
||||
next();
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Error Rate
|
||||
**Target**: <0.1% (1 in 1000)
|
||||
|
||||
```javascript
|
||||
let totalRequests = 0;
|
||||
let errorRequests = 0;
|
||||
|
||||
app.use((req, res, next) => {
|
||||
totalRequests++;
|
||||
if (res.statusCode >= 500) {
|
||||
errorRequests++;
|
||||
}
|
||||
|
||||
const errorRate = (errorRequests / totalRequests) * 100;
|
||||
metrics.gauge('http.error_rate', errorRate);
|
||||
next();
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Database Metrics
|
||||
|
||||
### Query Execution Time
|
||||
**Target**: p95 <50ms, p99 <100ms
|
||||
|
||||
```sql
|
||||
-- PostgreSQL: Enable query logging
|
||||
ALTER DATABASE mydb SET log_min_duration_statement = 100;
|
||||
|
||||
-- View slow queries
|
||||
SELECT query, mean_exec_time, calls
|
||||
FROM pg_stat_statements
|
||||
WHERE mean_exec_time > 100
|
||||
ORDER BY mean_exec_time DESC
|
||||
LIMIT 10;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Connection Pool Usage
|
||||
**Target**: <80% utilization
|
||||
|
||||
```javascript
|
||||
pool.on('acquire', () => {
|
||||
const active = pool.totalCount - pool.idleCount;
|
||||
const utilization = (active / pool.max) * 100;
|
||||
metrics.gauge('db.pool.utilization', utilization);
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Memory Metrics
|
||||
|
||||
### Heap Usage
|
||||
**Target**: <80% of max, stable over time
|
||||
|
||||
```javascript
|
||||
setInterval(() => {
|
||||
const usage = process.memoryUsage();
|
||||
metrics.gauge('memory.heap_used', usage.heapUsed);
|
||||
metrics.gauge('memory.heap_total', usage.heapTotal);
|
||||
metrics.gauge('memory.external', usage.external);
|
||||
}, 10000);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Lighthouse Scores
|
||||
|
||||
| Score | Performance | Accessibility | Best Practices | SEO |
|
||||
|-------|-------------|---------------|----------------|-----|
|
||||
| **Good** | 90-100 | 90-100 | 90-100 | 90-100 |
|
||||
| **Needs Improvement** | 50-89 | 50-89 | 50-89 | 50-89 |
|
||||
| **Poor** | 0-49 | 0-49 | 0-49 | 0-49 |
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
| Metric Category | Key Metrics | Tools |
|
||||
|----------------|-------------|-------|
|
||||
| **Web Vitals** | LCP, FID, CLS | Chrome DevTools, Lighthouse |
|
||||
| **Backend** | Latency, Throughput, Error Rate | APM, Prometheus |
|
||||
| **Database** | Query Time, Pool Usage | pg_stat_statements, APM |
|
||||
| **Memory** | Heap Usage, GC Time | Node.js profiler |
|
||||
|
||||
---
|
||||
|
||||
**Next**: [Profiling Tools](profiling-tools.md) | **Index**: [Reference Index](INDEX.md)
|
||||
158
skills/performance-optimization/reference/profiling-tools.md
Normal file
158
skills/performance-optimization/reference/profiling-tools.md
Normal file
@@ -0,0 +1,158 @@
|
||||
# Profiling Tools Reference
|
||||
|
||||
Tools and techniques for identifying performance bottlenecks across the stack.
|
||||
|
||||
## Chrome DevTools
|
||||
|
||||
### Performance Panel
|
||||
```javascript
|
||||
// Mark performance measurements
|
||||
performance.mark('start-expensive-operation');
|
||||
// ... expensive operation ...
|
||||
performance.mark('end-expensive-operation');
|
||||
performance.measure(
|
||||
'expensive-operation',
|
||||
'start-expensive-operation',
|
||||
'end-expensive-operation'
|
||||
);
|
||||
```
|
||||
|
||||
**Use for**: FPS analysis, JavaScript profiling, paint events, network waterfall
|
||||
|
||||
---
|
||||
|
||||
### Memory Panel
|
||||
- **Heap Snapshot**: Take snapshot, compare for memory leaks
|
||||
- **Allocation Timeline**: See memory allocation over time
|
||||
- **Allocation Sampling**: Low-overhead profiling
|
||||
|
||||
**Use for**: Memory leak detection, heap size analysis
|
||||
|
||||
---
|
||||
|
||||
## Node.js Profiling
|
||||
|
||||
### Built-in Inspector
|
||||
```bash
|
||||
# Start with inspector
|
||||
node --inspect server.js
|
||||
|
||||
# Open chrome://inspect in Chrome
|
||||
# Click "inspect" to open DevTools
|
||||
```
|
||||
|
||||
### clinic.js
|
||||
```bash
|
||||
# Install
|
||||
npm install -g clinic
|
||||
|
||||
# Doctor: Overall health check
|
||||
clinic doctor -- node server.js
|
||||
|
||||
# Flame: CPU profiling
|
||||
clinic flame -- node server.js
|
||||
|
||||
# Bubbleprof: Async operations
|
||||
clinic bubbleprof -- node server.js
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## React DevTools Profiler
|
||||
|
||||
```jsx
|
||||
import { Profiler } from 'react';
|
||||
|
||||
function onRenderCallback(
|
||||
id, phase, actualDuration, baseDuration, startTime, commitTime
|
||||
) {
|
||||
console.log(`${id} took ${actualDuration}ms to render`);
|
||||
}
|
||||
|
||||
<Profiler id="App" onRender={onRenderCallback}>
|
||||
<App />
|
||||
</Profiler>
|
||||
```
|
||||
|
||||
**Metrics**:
|
||||
- **Actual Duration**: Time to render committed update
|
||||
- **Base Duration**: Estimated time without memoization
|
||||
- **Start Time**: When React began rendering
|
||||
- **Commit Time**: When React committed the update
|
||||
|
||||
---
|
||||
|
||||
## Database Profiling
|
||||
|
||||
### PostgreSQL EXPLAIN ANALYZE
|
||||
```sql
|
||||
EXPLAIN ANALYZE
|
||||
SELECT * FROM orders
|
||||
WHERE customer_id = '123'
|
||||
AND status = 'pending';
|
||||
|
||||
-- Output shows:
|
||||
-- - Execution time
|
||||
-- - Rows scanned
|
||||
-- - Index usage
|
||||
-- - Cost estimates
|
||||
```
|
||||
|
||||
### pg_stat_statements
|
||||
```sql
|
||||
-- Enable extension
|
||||
CREATE EXTENSION pg_stat_statements;
|
||||
|
||||
-- View top slow queries
|
||||
SELECT
|
||||
query,
|
||||
mean_exec_time,
|
||||
calls,
|
||||
total_exec_time
|
||||
FROM pg_stat_statements
|
||||
ORDER BY mean_exec_time DESC
|
||||
LIMIT 10;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## APM Tools
|
||||
|
||||
### DataDog
|
||||
```javascript
|
||||
const tracer = require('dd-trace').init();
|
||||
|
||||
tracer.trace('expensive-operation', () => {
|
||||
// Your code here
|
||||
});
|
||||
```
|
||||
|
||||
### Sentry Performance
|
||||
```javascript
|
||||
import * as Sentry from '@sentry/node';
|
||||
|
||||
const transaction = Sentry.startTransaction({
|
||||
op: 'task',
|
||||
name: 'Process Order'
|
||||
});
|
||||
|
||||
// ... do work ...
|
||||
|
||||
transaction.finish();
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
| Tool | Use Case | Best For |
|
||||
|------|----------|----------|
|
||||
| **Chrome DevTools** | Frontend profiling | JavaScript, rendering, network |
|
||||
| **clinic.js** | Node.js profiling | CPU, async, I/O |
|
||||
| **React Profiler** | Component profiling | React performance |
|
||||
| **EXPLAIN ANALYZE** | Query profiling | Database optimization |
|
||||
| **APM Tools** | Production monitoring | Distributed tracing |
|
||||
|
||||
---
|
||||
|
||||
**Previous**: [Performance Metrics](performance-metrics.md) | **Next**: [Optimization Patterns](optimization-patterns.md) | **Index**: [Reference Index](INDEX.md)
|
||||
Reference in New Issue
Block a user