GitHub Actions 为开发者提供了 workflow 控制,还有每个月 2000 分钟的机器使用时间(免费额度)。但拿它做性能测试,得到的结果未必准确。
issue-2 是我尝试将 etcd PR 性能测试自动化的努力,但是它以失败结束。
这个实验在 GitHub Actions 上跑了很多遍,得到的结果都类似:
同样的代码,在同样规格的 GitHub runner 上运行 2 次,性能可以差异超过 40%
为了得到准确的实验结果,我决定用自己的机器跑性能测试脚本。于是我将自己的机器加入 GitHub self-hosted runners;这样,我在 GitHub 上触发的 Action 将跑在我自己的机器上。
但是,这并不能完全保证实验结果的准确。
不久之前,我就发现过一个严重的问题:
用同样的脚本,在同一台机器上,测试 PR 和 main 分支的代码,先运行的脚本会得到更高的吞吐量(高达 30%)。这一度误导我,让我以为 PR 分支有着巨大的性能提升。直到我增加了一个对照组——将 main 分支测试 2 遍。
这是我增加对照组后的测试流程(测试结果):
1. 编译 main 分支的代码,对二进制程序进行性能测试;
2. 编译 PR 分支的代码,对二进制程序进行性能测试;
3. 再次编译 main 分支的代码,对二进制程序进行性能测试,作为对照组。
于是问题暴露出来了:对 main 分支的 2 次性能测试,得到的结果差异很大——先测试的总是表现出更好的性能(高达 30%)。
但是机器并没有明显的信号可以解释这 30% 的误差,因为每次脚本运行完毕,机器的磁盘读写速度、CPU 负载、内存以及 Swap(0B)都恢复正常水平,并且 top 显示的进程列表也没有出现异常进程。
为了绕过这个问题,我尝试在每次运行完测试脚本后重启机器。
这是我增加重启机器步骤后的测试流程(测试结果):
1. 编译 main 分支的代码,对二进制程序进行性能测试;
2. 重启机器
3. 编译 PR 分支的代码,对二进制程序进行性能测试;
4. 重启机器
5. 再次编译 main 分支的代码,对二进制程序进行性能测试,作为对照组。
终于得到误差范围内的测试结果,之后的每次性能测试,我都会增加一个对照组,用来确保测试环境是可信任的。
将这个测试流程自动化,需要先处理掉一个麻烦:重启机器会导致 GitHub workflow 中断和失败,并且不容易绕过,互联网上也没有成功的经验可以借鉴。
等到天又亮时,我还是摸索出了一个方案,虽然不太优雅,但是能稳定运行。
这个方案有 2 个关键点:
sleep 180s在 ubuntu-latest 机器睡眠期间,self-hosted 机器可以自由地重启,并且不会中断 workflow。
/home/gh/monitor 文件里写入数据。为什么不在这个 hook 中重启机器?因为那将有很大概率导致 GitHub runner 来不及将当前 job 的完成结果上传到 GitHub 服务器,导致 workflow 失败。
完整步骤参考以下文件:
使用 GitHub Actions 做性能测试,需要注意:
reboot都会导致 workflow 失败。failed to fetch permalinkfailed to fetch permalinkfailed to fetch permalinkfailed to fetch permalink