解决方案
2023 年 7 月,Ramp 的 Python 单体测试套件运行需要 45 分钟,缓慢的测试拖累了全公司的合并队列——工程师们仅仅为了照看待处理的变更就要空出半天时间。两年前,一篇内部文章已经指出缓慢的测试会损害工程生产力,但此后一直没有任何行动。
团队没有承诺进行大规模重写,而是先进行测量:45 分钟中约有 38 分钟来自 pytest 调用本身。性能分析显示测试运行受 CPU 限制,因此第一个修复方案——更快的 CPU——本身就使运行时间缩短了约 50%,这是整个项目中最大的单项收益,也是发现成本最低的一项。
在此基础上,工程师们分头行动,并行开展低成本的实验,范围限定在各自已有上下文的领域:在自托管运行器上使用 Docker 层缓存节省了一分多钟;重写 pytest-xdist 的工作拆分算法节省了 2-3 分钟;增加测试数据库并调整 Postgres 连接设置,解决了超过 20 个工作进程访问同一数据库时的锁争用问题。并非每个实验都有回报——将测试数据挂载到 RAM 中没有带来任何收益,因此被放弃——但每个实验的成本都足够低,值得一试。
取得了什么成果
追逐成本低、潜在收益高的实验,并在收益递减的那一刻停止
为什么有效
先测量(45 分钟中有 38 分钟是 pytest 调用本身,受 CPU 限制)意味着团队修复了真正的瓶颈,而不是靠猜测。
先做杠杆最高、成本最低的修复(更快的 CPU,约 50% 的收益)建立了势头,并腾出时间去探索风险更高的想法。
拆分为并行、低成本的实验,让团队能够快速验证许多假设,而不是把所有赌注押在一个大变更上。
绘制每次变更节省的时间,使收益递减曲线变得可见,为团队提供了一个具体的停止信号,而不是为了边际收益继续打磨。
可以应用什么
在调优之前先测量,先修复杠杆最高的项目,然后并行运行一组低成本的实验组合——并将每次收益的缩小作为停止的信号。
后续
一周后,套件运行时间不到 5 分钟,相比最初的 45 分钟减少了约 70% 以上。到周末时,新的改进只能从运行时间中削减几秒钟(不到 5%),团队以此作为停止的信号,并将剩余的想法移入长尾待办事项,而不是继续调优。
从这里,追溯依据
参考来源
- Picking Low Hanging Fruit Ramp Engineering · builders.ramp.com ·