performance-optimizer
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePerformance Optimizer
性能优化指南
Find and fix performance bottlenecks. Measure, optimize, verify. Make it fast.
查找并修复性能瓶颈,遵循测量、优化、验证的流程,让系统运行得更快。
When to Use This Skill
适用场景
- App is slow or laggy
- User complains about performance
- Page load times are high
- API responses are slow
- Database queries take too long
- User mentions "slow", "lag", "performance", or "optimize"
- 应用运行缓慢或卡顿
- 用户反馈性能问题
- 页面加载时间过长
- API响应慢
- 数据库查询耗时太久
- 用户提到「慢」、「卡顿」、「性能」或「优化」相关关键词
The Optimization Process
优化流程
1. Measure First
1. 先进行性能测量
Never optimize without measuring:
javascript
// Measure execution time
console.time('operation');
await slowOperation();
console.timeEnd('operation'); // operation: 2341msWhat to measure:
- Page load time
- API response time
- Database query time
- Function execution time
- Memory usage
- Network requests
永远不要在没有测量的情况下盲目优化:
javascript
// Measure execution time
console.time('operation');
await slowOperation();
console.timeEnd('operation'); // operation: 2341ms需要测量的指标:
- 页面加载时间
- API响应时间
- 数据库查询时间
- 函数执行时间
- 内存占用
- 网络请求情况
2. Find the Bottleneck
2. 定位性能瓶颈
Use profiling tools to find the slow parts:
Browser:
DevTools → Performance tab → Record → Stop
Look for long tasks (red bars)Node.js:
bash
node --prof app.js
node --prof-process isolate-*.log > profile.txtDatabase:
sql
EXPLAIN ANALYZE SELECT * FROM users WHERE email = 'test@example.com';使用分析工具找到运行缓慢的部分:
浏览器端:
DevTools → Performance tab → Record → Stop
查找长任务(红色条形块)Node.js端:
bash
node --prof app.js
node --prof-process isolate-*.log > profile.txt数据库端:
sql
EXPLAIN ANALYZE SELECT * FROM users WHERE email = 'test@example.com';3. Optimize
3. 执行优化
Fix the slowest thing first (biggest impact).
优先修复影响最大的最慢部分,投入产出比最高。
Common Optimizations
常见优化方案
Database Queries
数据库查询优化
Problem: N+1 Queries
javascript
// Bad: N+1 queries
const users = await db.users.find();
for (const user of users) {
user.posts = await db.posts.find({ userId: user.id }); // N queries
}
// Good: Single query with JOIN
const users = await db.users.find()
.populate('posts'); // 1 queryProblem: Missing Index
sql
-- Check slow query
EXPLAIN SELECT * FROM users WHERE email = 'test@example.com';
-- Shows: Seq Scan (bad)
-- Add index
CREATE INDEX idx_users_email ON users(email);
-- Check again
EXPLAIN SELECT * FROM users WHERE email = 'test@example.com';
-- Shows: Index Scan (good)**Problem: SELECT ***
javascript
// Bad: Fetches all columns
const users = await db.query('SELECT * FROM users');
// Good: Only needed columns
const users = await db.query('SELECT id, name, email FROM users');Problem: No Pagination
javascript
// Bad: Returns all records
const users = await db.users.find();
// Good: Paginated
const users = await db.users.find()
.limit(20)
.skip((page - 1) * 20);问题:N+1查询
javascript
// Bad: N+1 queries
const users = await db.users.find();
for (const user of users) {
user.posts = await db.posts.find({ userId: user.id }); // N queries
}
// Good: Single query with JOIN
const users = await db.users.find()
.populate('posts'); // 1 query问题:缺少索引
sql
-- Check slow query
EXPLAIN SELECT * FROM users WHERE email = 'test@example.com';
-- Shows: Seq Scan (bad)
-- Add index
CREATE INDEX idx_users_email ON users(email);
-- Check again
EXPLAIN SELECT * FROM users WHERE email = 'test@example.com';
-- Shows: Index Scan (good)问题:查询所有字段
javascript
// Bad: Fetches all columns
const users = await db.query('SELECT * FROM users');
// Good: Only needed columns
const users = await db.query('SELECT id, name, email FROM users');问题:没有分页
javascript
// Bad: Returns all records
const users = await db.users.find();
// Good: Paginated
const users = await db.users.find()
.limit(20)
.skip((page - 1) * 20);API Performance
API性能优化
Problem: No Caching
javascript
// Bad: Hits database every time
app.get('/api/stats', async (req, res) => {
const stats = await db.stats.calculate(); // Slow
res.json(stats);
});
// Good: Cache for 5 minutes
const cache = new Map();
app.get('/api/stats', async (req, res) => {
const cached = cache.get('stats');
if (cached && Date.now() - cached.time < 300000) {
return res.json(cached.data);
}
const stats = await db.stats.calculate();
cache.set('stats', { data: stats, time: Date.now() });
res.json(stats);
});Problem: Sequential Operations
javascript
// Bad: Sequential (slow)
const user = await getUser(id);
const posts = await getPosts(id);
const comments = await getComments(id);
// Total: 300ms + 200ms + 150ms = 650ms
// Good: Parallel (fast)
const [user, posts, comments] = await Promise.all([
getUser(id),
getPosts(id),
getComments(id)
]);
// Total: max(300ms, 200ms, 150ms) = 300msProblem: Large Payloads
javascript
// Bad: Returns everything
res.json(users); // 5MB response
// Good: Only needed fields
res.json(users.map(u => ({
id: u.id,
name: u.name,
email: u.email
}))); // 500KB response问题:没有缓存
javascript
// Bad: Hits database every time
app.get('/api/stats', async (req, res) => {
const stats = await db.stats.calculate(); // Slow
res.json(stats);
});
// Good: Cache for 5 minutes
const cache = new Map();
app.get('/api/stats', async (req, res) => {
const cached = cache.get('stats');
if (cached && Date.now() - cached.time < 300000) {
return res.json(cached.data);
}
const stats = await db.stats.calculate();
cache.set('stats', { data: stats, time: Date.now() });
res.json(stats);
});问题:串行执行操作
javascript
// Bad: Sequential (slow)
const user = await getUser(id);
const posts = await getPosts(id);
const comments = await getComments(id);
// Total: 300ms + 200ms + 150ms = 650ms
// Good: Parallel (fast)
const [user, posts, comments] = await Promise.all([
getUser(id),
getPosts(id),
getComments(id)
]);
// Total: max(300ms, 200ms, 150ms) = 300ms问题:返回 payload 过大
javascript
// Bad: Returns everything
res.json(users); // 5MB response
// Good: Only needed fields
res.json(users.map(u => ({
id: u.id,
name: u.name,
email: u.email
}))); // 500KB responseFrontend Performance
前端性能优化
Problem: Unnecessary Re-renders
javascript
// Bad: Re-renders on every parent update
function UserList({ users }) {
return users.map(user => <UserCard user={user} />);
}
// Good: Memoized
const UserCard = React.memo(({ user }) => {
return <div>{user.name}</div>;
});Problem: Large Bundle
javascript
// Bad: Imports entire library
import _ from 'lodash'; // 70KB
// Good: Import only what you need
import debounce from 'lodash/debounce'; // 2KBProblem: No Code Splitting
javascript
// Bad: Everything in one bundle
import HeavyComponent from './HeavyComponent';
// Good: Lazy load
const HeavyComponent = React.lazy(() => import('./HeavyComponent'));Problem: Unoptimized Images
html
<!-- Bad: Large image -->
<img src="photo.jpg" /> <!-- 5MB -->
<!-- Good: Optimized and responsive -->
<img
src="photo-small.webp"
srcset="photo-small.webp 400w, photo-large.webp 800w"
loading="lazy"
width="400"
height="300"
/> <!-- 50KB -->问题:不必要的重渲染
javascript
// Bad: Re-renders on every parent update
function UserList({ users }) {
return users.map(user => <UserCard user={user} />);
}
// Good: Memoized
const UserCard = React.memo(({ user }) => {
return <div>{user.name}</div>;
});问题:打包体积过大
javascript
// Bad: Imports entire library
import _ from 'lodash'; // 70KB
// Good: Import only what you need
import debounce from 'lodash/debounce'; // 2KB问题:没有代码分割
javascript
// Bad: Everything in one bundle
import HeavyComponent from './HeavyComponent';
// Good: Lazy load
const HeavyComponent = React.lazy(() => import('./HeavyComponent'));问题:图片未优化
html
<!-- Bad: Large image -->
<img src="photo.jpg" /> <!-- 5MB -->
<!-- Good: Optimized and responsive -->
<img
src="photo-small.webp"
srcset="photo-small.webp 400w, photo-large.webp 800w"
loading="lazy"
width="400"
height="300"
/> <!-- 50KB -->Algorithm Optimization
算法优化
Problem: Inefficient Algorithm
javascript
// Bad: O(n²) - nested loops
function findDuplicates(arr) {
const duplicates = [];
for (let i = 0; i < arr.length; i++) {
for (let j = i + 1; j < arr.length; j++) {
if (arr[i] === arr[j]) duplicates.push(arr[i]);
}
}
return duplicates;
}
// Good: O(n) - single pass with Set
function findDuplicates(arr) {
const seen = new Set();
const duplicates = new Set();
for (const item of arr) {
if (seen.has(item)) duplicates.add(item);
seen.add(item);
}
return Array.from(duplicates);
}Problem: Repeated Calculations
javascript
// Bad: Calculates every time
function getTotal(items) {
return items.reduce((sum, item) => sum + item.price * item.quantity, 0);
}
// Called 100 times in render
// Good: Memoized
const getTotal = useMemo(() => {
return items.reduce((sum, item) => sum + item.price * item.quantity, 0);
}, [items]);问题:低效算法
javascript
// Bad: O(n²) - nested loops
function findDuplicates(arr) {
const duplicates = [];
for (let i = 0; i < arr.length; i++) {
for (let j = i + 1; j < arr.length; j++) {
if (arr[i] === arr[j]) duplicates.push(arr[i]);
}
}
return duplicates;
}
// Good: O(n) - single pass with Set
function findDuplicates(arr) {
const seen = new Set();
const duplicates = new Set();
for (const item of arr) {
if (seen.has(item)) duplicates.add(item);
seen.add(item);
}
return Array.from(duplicates);
}问题:重复计算
javascript
// Bad: Calculates every time
function getTotal(items) {
return items.reduce((sum, item) => sum + item.price * item.quantity, 0);
}
// Called 100 times in render
// Good: Memoized
const getTotal = useMemo(() => {
return items.reduce((sum, item) => sum + item.price * item.quantity, 0);
}, [items]);Memory Optimization
内存优化
Problem: Memory Leak
javascript
// Bad: Event listener not cleaned up
useEffect(() => {
window.addEventListener('scroll', handleScroll);
// Memory leak!
}, []);
// Good: Cleanup
useEffect(() => {
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, []);Problem: Large Data in Memory
javascript
// Bad: Loads entire file into memory
const data = fs.readFileSync('huge-file.txt'); // 1GB
// Good: Stream it
const stream = fs.createReadStream('huge-file.txt');
stream.on('data', chunk => process(chunk));问题:内存泄漏
javascript
// Bad: Event listener not cleaned up
useEffect(() => {
window.addEventListener('scroll', handleScroll);
// Memory leak!
}, []);
// Good: Cleanup
useEffect(() => {
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, []);问题:内存中加载大量数据
javascript
// Bad: Loads entire file into memory
const data = fs.readFileSync('huge-file.txt'); // 1GB
// Good: Stream it
const stream = fs.createReadStream('huge-file.txt');
stream.on('data', chunk => process(chunk));Measuring Impact
验证优化效果
Always measure before and after:
javascript
// Before optimization
console.time('query');
const users = await db.users.find();
console.timeEnd('query');
// query: 2341ms
// After optimization (added index)
console.time('query');
const users = await db.users.find();
console.timeEnd('query');
// query: 23ms
// Improvement: 100x faster!优化前后必须进行性能测量:
javascript
// Before optimization
console.time('query');
const users = await db.users.find();
console.timeEnd('query');
// query: 2341ms
// After optimization (added index)
console.time('query');
const users = await db.users.find();
console.timeEnd('query');
// query: 23ms
// Improvement: 100x faster!Performance Budgets
性能预算
Set targets:
Page Load: < 2 seconds
API Response: < 200ms
Database Query: < 50ms
Bundle Size: < 200KB
Time to Interactive: < 3 seconds设置性能目标:
页面加载时间: < 2秒
API响应时间: < 200ms
数据库查询时间: < 50ms
打包体积: < 200KB
可交互时间: < 3秒Tools
工具推荐
Browser:
- Chrome DevTools Performance tab
- Lighthouse (audit)
- Network tab (waterfall)
Node.js:
- (profiling)
node --prof - (diagnostics)
clinic - (load testing)
autocannon
Database:
- (query plans)
EXPLAIN ANALYZE - Slow query log
- Database profiler
Monitoring:
- New Relic
- Datadog
- Sentry Performance
浏览器端:
- Chrome DevTools Performance tab
- Lighthouse (性能审计)
- Network tab (瀑布图分析)
Node.js端:
- (性能分析)
node --prof - (诊断工具)
clinic - (压力测试)
autocannon
数据库端:
- (查询执行计划分析)
EXPLAIN ANALYZE - 慢查询日志
- 数据库分析器
监控工具:
- New Relic
- Datadog
- Sentry Performance
Quick Wins
高效优化小技巧
Easy optimizations with big impact:
- Add database indexes on frequently queried columns
- Enable gzip compression on server
- Add caching for expensive operations
- Lazy load images and heavy components
- Use CDN for static assets
- Minify and compress JavaScript/CSS
- Remove unused dependencies
- Use pagination instead of loading all data
- Optimize images (WebP, proper sizing)
- Enable HTTP/2 on server
投入低、收益高的简单优化项:
- 为高频查询的字段添加数据库索引
- 服务端开启gzip压缩
- 为耗时操作添加缓存
- 图片和重型组件懒加载
- 静态资源使用CDN加速
- 压缩混淆JavaScript/CSS代码
- 移除未使用的依赖
- 使用分页代替全量加载数据
- 优化图片(使用WebP格式、匹配尺寸)
- 服务端开启HTTP/2
Optimization Checklist
优化检查清单
- Measured current performance
- Identified bottleneck
- Applied optimization
- Measured improvement
- Verified functionality still works
- No new bugs introduced
- Documented the change
- 已测量当前性能基线
- 已定位到性能瓶颈
- 已应用优化方案
- 已测量优化后的性能提升
- 已验证功能正常运行
- 未引入新的bug
- 已记录优化变更
When NOT to Optimize
不需要优化的场景
- Premature optimization (optimize when it's actually slow)
- Micro-optimizations (save 1ms when page takes 5 seconds)
- Readable code is more important than tiny speed gains
- If it's already fast enough
- 过早优化:只有当系统确实运行缓慢时再优化
- 微优化:页面加载需要5秒时,没必要为了节省1ms耗费精力
- 可读性比微小的速度提升更重要
- 性能已经满足需求时不需要额外优化
Key Principles
核心原则
- Measure before optimizing
- Fix the biggest bottleneck first
- Measure after to prove improvement
- Don't sacrifice readability for tiny gains
- Profile in production-like environment
- Consider the 80/20 rule (20% of code causes 80% of slowness)
- 优化前先测量性能
- 优先修复影响最大的瓶颈
- 优化后测量验证提升效果
- 不要为了微小的性能提升牺牲代码可读性
- 在接近生产的环境中做性能分析
- 遵循80/20原则:20%的代码导致了80%的性能问题
Related Skills
相关技能
- - Query optimization
@database-design - - Code review
@codebase-audit-pre-push - - Debugging
@bug-hunter
- - 查询优化
@database-design - - 代码审查
@codebase-audit-pre-push - - 调试
@bug-hunter