Optimization
当任务涉及让系统更快、更轻、更具可扩展性或整体更高效时,可使用本技能。
核心原则
要正确地进行优化,你必须知道:
- 你正在追求哪些指标
- 真正的瓶颈在哪里
不要盲目优化。
- 先定义目标指标
在修改代码之前,确保你有正确的测量方式。
识别真正重要的确切指标:延迟、吞吐量、内存、CPU、启动时间、编译时间、查询次数、token 用量、成本等。
要全面测量,而不是只测量方便的那一部分。
确保指标准确并能够代表真实工作负载。
优先选择运行快速的测量方式,以便快速迭代。
如果可能,创建可重复的基准测试或脚本,使改进可被验证。
- 获得完整的瓶颈归因
你应当对系统各部分正在做什么有强有力的归因。
对系统进行插桩,以便看到时间和资源都花在哪里。
优先同时具备:
- 用于快速调试的临时性检查
- 用于后续分析和对比的日志化测量
要在完整路径上归因工作,而不仅仅是明显较慢的组件。
确保数据足够详细,能够解释成本来自哪里。
如果你能通过日志或追踪在事后分析运行情况,这通常比只依赖实时检查强大得多。
- 也要使用静态分析
并非每个优化问题都需要先做运行时性能分析。很多时候,代码检查就能揭示问题。
检查:
- 错误的渐近复杂度
- 错误的算法或数据结构
- 不必要的重复工作
- 工作在错误的层面发生
- 低效的架构或控制流
- 方向不正确的做法
在调优细节之前,确保渐近复杂度正确,整体算法合理。
- 先宏观优化,再微观优化
优先处理最大的收益点。
先移除整类工作,再让现有工作稍微便宜一点。
在关注细小的低层调整之前,先修复架构、批处理、缓存、查询模式、算法选择、并行化和数据移动。
如果你距离预期指标还很远,就在宏观优化上花更多时间。
微观优化在主要低效问题已经解决之后才最重要。
推荐工作流
- 定义成功指标。
- 复现当前基线。
- 如果缺少测量和归因,则补上。
- 识别最大瓶颈。
- 检查算法或架构问题。
- 优先应用最高杠杆的修复。
- 重新测量。
- 重复,直到达到目标或权衡不再值得。
护栏
- 没有前后对比证据,不要声称完成了优化。
- 小心不要优化了错误的指标。
- 注意正确性、可靠性、可维护性和安全性方面的回归。
- 优先选择可测量、可解释、可回滚的改动。