性能优化
性能优化工作流程
复制此清单并跟踪进度:
性能优化进度:
- [ ] 第1步:测量基准性能
- [ ] 第2步:识别瓶颈
- [ ] 第3步:应用针对性优化
- [ ] 第4步:再次测量并比较
- [ ] 第5步:如果目标未达成则重复
关键规则:没有数据不要优化。变化前后都要进行性能分析。
第1步:测量基准
分析命令
# Node.js性能分析
node --prof app.js
node --prof-process isolate*.log > profile.txt
# Python性能分析
python -m cProfile -o profile.stats app.py
python -m pstats profile.stats
# Web性能
lighthouse https://example.com --output=json
第2步:识别瓶颈
常见瓶颈类别
| 类别 | 症状 | 工具 |
|---|---|---|
| CPU | 高CPU使用率,计算缓慢 | 分析器,火焰图 |
| 内存 | 高RAM,GC暂停,OOM | 堆快照,内存分析器 |
| I/O | 磁盘/网络缓慢,等待 | strace,网络检查器 |
| 数据库 | 查询缓慢,锁争用 | 查询分析器,EXPLAIN |
第3步:应用优化
前端优化
包大小:
// ❌ 导入整个库
import _ from 'lodash';
// ✅ 只导入需要的函数
import debounce from 'lodash/debounce';
// ✅ 使用动态导入进行代码分割
const HeavyComponent = lazy(() => import('./HeavyComponent'));
渲染:
// ❌ 每次父组件更新时渲染
function Child({ data }) {
return <ExpensiveComponent data={data} />;
}
// ✅ 当props不变时使用memo
const Child = memo(function Child({ data }) {
return <ExpensiveComponent data={data} />;
});
// ✅ 使用useMemo进行昂贵的计算
const processed = useMemo(() => expensiveCalc(data), [data]);
图片:
<!-- ❌ 未优化 -->
<img src="large-image.jpg" />
<!-- ✅ 优化 -->
<img
src="image.webp"
srcset="image-300.webp 300w, image-600.webp 600w"
sizes="(max-width: 600px) 300px, 600px"
loading="lazy"
decoding="async"
/>
后端优化
数据库查询:
-- ❌ N+1查询问题
SELECT * FROM users;
-- 然后对每个用户:
SELECT * FROM orders WHERE user_id = ?;
-- ✅ 使用JOIN的单查询
SELECT u.*, o.*
FROM users u
LEFT JOIN orders o ON u.id = o.user_id;
-- ✅ 或者使用分页
SELECT * FROM users LIMIT 100 OFFSET 0;
缓存策略:
// 多层缓存
const getUser = async (id) => {
// L1:内存缓存(最快)
let user = memoryCache.get(`user:${id}`);
if (user) return user;
// L2:Redis缓存(快)
user = await redis.get(`user:${id}`);
if (user) {
memoryCache.set(`user:${id}`, user, 60);
return JSON.parse(user);
}
// L3:数据库(慢)
user = await db.users.findById(id);
await redis.setex(`user:${id}`, 3600, JSON.stringify(user));
memoryCache.set(`user:${id}`, user, 60);
return user;
};
异步处理:
// ❌ 阻塞操作
app.post('/upload', async (req, res) => {
await processVideo(req.file); // 需要5分钟
res.send('Done');
});
// ✅ 后台处理队列
app.post('/upload', async (req, res) => {
const jobId = await queue.add('processVideo', { file: req.file });
res.send({ jobId, status: 'processing' });
});
算法优化
// ❌ O(n²) - 嵌套循环
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;
}
// ✅ O(n) - 哈希映射
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 [...duplicates];
}
第4步:再次测量
应用优化后,重新运行性能分析并比较:
比较清单:
- [ ] 运行与基准相同的分析工具
- [ ] 比较变化前后的指标
- [ ] 验证其他区域没有退步
- [ ] 文档记录改进百分比
性能目标
Web Vitals
| 指标 | 良好 | 需要改进 | 差 |
|---|---|---|---|
| LCP | < 2.5s | 2.5-4s | > 4s |
| FID | < 100ms | 100-300ms | > 300ms |
| CLS | < 0.1 | 0.1-0.25 | > 0.25 |
| TTFB | < 800ms | 800ms-1.8s | > 1.8s |
API性能
| 指标 | 目标 |
|---|---|
| P50延迟 | < 100ms |
| P95延迟 | < 500ms |
| P99延迟 | < 1s |
| 错误率 | < 0.1% |
验证
优化后验证结果:
性能验证:
- [ ] 与基准相比指标有所提高
- [ ] 没有功能退步
- [ ] 没有引入新的错误
- [ ] 变更是可持续的(不是一次性修复)
- [ ] 文档记录性能提升
如果目标未达成,返回第2步并识别剩余瓶颈。