name: 优化性能 description: 测量先行的性能优化,平衡收益与复杂性。用于解决代码缓慢、分析问题或评估优化权衡。
优化性能
核心原则: 可读的代码“足够快”胜过复杂的“最优”代码。测量先行。
黄金规则
如果优化降低复杂性并提高性能 → 总是执行
如果优化增加复杂性 → 仅当速度提升10倍或修复关键用户体验(>16毫秒UI,>100毫秒输入)时执行
四阶段流程
- [ ] 阶段1:测量基线(时间/渲染次数/内存/KB)
- [ ] 阶段2:识别根本原因(算法/I/O/负载)
- [ ] 阶段3:评估成本与收益
- [ ] 阶段4:实施并验证改进
阶段1:先测量(必需)
没有数据永不优化。
| 指标 | 要计数的内容 | 工具 |
|---|---|---|
| 时间 | 每次操作的毫秒数 | performance.now()、分析器 |
| 重新渲染 | 组件渲染次数 | React DevTools 分析器 |
| 内存 | 分配的MB | DevTools 内存标签 |
| 网络 | 请求次数、KB | 网络标签、打包分析器 |
| 数据库 | 查询次数、扫描行数 | EXPLAIN 计划 |
阶段2:识别根本原因
| 问题 | 指示器 | 修复方向 |
|---|---|---|
| O(n²) 复杂度 | 嵌套循环、循环中的 .includes() |
使用 Set/Map |
| 不必要的工作 | 重新计算相同结果 | 缓存/记忆化 |
| I/O 瓶颈 | N+1 查询、顺序API | 批量处理、使用连接 |
| 大型数据集 | 渲染1000+个项目 | 虚拟化 |
| 负载大小 | >500KB 打包 | 树摇、懒加载 |
阶段3:评估成本与收益
- 降低复杂性? → 总是执行
- 增加复杂性? → 仅当速度提升10倍或修复关键用户体验时执行
- 否则 → 不执行
阶段4:实施并验证
- 针对瓶颈进行最小化更改
- 重新运行基准测试
- 验证测试通过
双赢优化(总是执行)
多循环 → 单循环:
// ❌ 三次遍历
const ids = users.map(u => u.id);
const active = users.filter(u => u.active);
// ✅ 一次遍历
const { ids, active } = users.reduce((acc, u) => {
acc.ids.push(u.id);
if (u.active) acc.active.push(u);
return acc;
}, { ids: [], active: [] });
嵌套循环 → 哈希映射(O(n²) → O(n)):
// ❌ O(n²)
const matched = orders.filter(o => users.some(u => u.id === o.userId));
// ✅ O(n)
const userIds = new Set(users.map(u => u.id));
const matched = orders.filter(o => userIds.has(o.userId));
高价值优化
| 模式 | 何时使用 | 修复方法 |
|---|---|---|
| 虚拟化 | 列表 >1000 个项目 | react-window、tanstack-virtual |
| 记忆化 | >5毫秒计算或不必要的重新渲染 | useMemo、React.memo |
| 批量处理 | 多个状态更新 | 单次 setState、批量 INSERT |
| 懒加载 | 大型依赖 | import('./heavy-lib') |
红色标志
- 无基准数据优化
- 微优化 <16毫秒代码
- 为微小增益增加复杂性
- 优化不常运行的代码