如何使用 Bencher 在 CI 中跟踪基准测试
大多数基准测试结果是短暂的。 它们会在终端达到其滚动限制时消失。 一些基准测试工具允许您缓存结果,但大多数仅在本地进行。 Bencher 使您能够追踪本地和 CI 运行的基准测试并比较结果,同时仍然使用您喜欢的基准测试工具。
在持续基准测试中,也就是 CI 中的基准测试,有三种比较基准测试结果的流行方法:
- 统计持续基准测试
- 随时间跟踪基准测试结果以创建基线
- 使用此基线及统计阈值创建统计边界
- 将新结果与此统计边界进行比较以检测性能回归
- 相对持续基准测试
- 为当前基线代码运行基准测试
- 切换到新版本代码
- 使用百分比阈值为基线代码创建边界
- 为新版本代码运行基准测试
- 将新版本代码结果与基线代码结果进行比较以检测性能回归
- 变更点检测
- 偶尔为新版本代码运行基准测试
- 使用变更点检测算法来检测性能回归
- 使用二分法查找引入性能回归的提交
统计连续基准测试
从我们在快速开始和Docker 自托管教程中离开的地方继续,
让我们为我们的claimed项目添加统计连续基准测试。
🐰 请确保您已经 创建了一个 API 令牌并将其设置为
BENCHER_API_TOKEN环境变量 然后再继续!
现在我们准备在 CI 中运行我们的基准测试。 因为每个 CI 环境都有些不同, 以下示例旨在说明而非实用。 有关更具体的示例,请参见在 GitHub Actions 中的连续基准测试 和在 GitLab CI/CD 中的连续基准测试。
首先,我们需要通过在 CI 中为每次更改进行基准测试来创建和维护我们main分支的历史基线:
bencher run \--project project-abc4567-wxyz123456789 \--branch main \--testbed ci-runner \--threshold-measure latency \--threshold-test t_test \--threshold-max-sample-size 64 \--threshold-upper-boundary 0.99 \--thresholds-reset \--err \--adapter json \bencher mock- 使用
bencher runCLI 子命令 运行您的main分支基准测试。 查看bencher runCLI 子命令以获取完整概述。 (例如:bencher run) - 设置
--project选项为项目 slug。 查看有关--project的文档以获取更多详情。 (例如:--project project-abc4567-wxyz123456789) - 设置
--branch选项为基础分支名称。 查看有关--branch的文档以获取完整概述。 (例如:--branch main) - 设置
--testbed选项为 CI 运行器测试台名称。 查看有关--testbed的文档以获取更多详情。 (例如:--testbed ci-runner) - 为
main分支、ci-runner测试台和latency测量设置阈值:- 将
--threshold-measure选项设置为由bencher mock生成的内置latency测量。 查看关于--threshold-measure的文档以获取更多详情。 (例如:--threshold-measure latency) - 将
--threshold-test选项设置为学生 t 检验(t_test)。 查看关于--threshold-test的文档以获取完整概述。 (例如:--threshold-test t_test) - 设置
--threshold-max-sample-size选项为最大样本大小64。 查看关于--threshold-max-sample-size的文档以获取更多详情。 (例如:--threshold-max-sample-size 64) - 设置
--threshold-upper-boundary选项为上限0.99。 查看关于--threshold-upper-boundary的文档以获取更多详情。 (例如:--threshold-upper-boundary 0.99) - 设置
--thresholds-reset标志以仅激活指定的阈值。 查看关于--thresholds-reset的文档以获取完整概述。 (例如:--thresholds-reset)
- 将
- 设置
--err标志以在生成警报时让命令失败。 查看关于--err的文档以获取完整概述。 (例如:--err) - 设置
--adapter选项为由bencher mock生成的Bencher Metric Format JSON(json)。 查看基准测试工具适配器以获取完整概述。 (例如:--adapter json) - 指定基准测试命令参数。
查看基准测试命令以获取完整概述。
(例如:
bencher mock)
第一次在 CI 中运行此命令时,
如果main分支尚不存在,它将被创建。
新的main将_不会_有起始点或现有数据。
将为main分支、ci-runner测试台和latency测量创建一个阈值。
在后续运行中,新数据将添加到main分支中。
然后将使用指定的阈值来检测性能回归。
现在,我们准备在 CI 中捕获性能回归。
这是我们将在 CI 中跟踪新功能分支性能的方法,恰如其名为feature-branch:
bencher run \--project project-abc4567-wxyz123456789 \--branch feature-branch \--start-point main \--start-point-hash 32aea434d751648726097ed3ac760b57107edd8b \--start-point-clone-thresholds \--start-point-reset \--testbed ci-runner \--err \--adapter json \bencher mock- 使用
bencher runCLI 子命令 运行您的feature-branch分支基准测试。 查看bencher runCLI 子命令以获取完整概述。 (例如:bencher run) - 设置
--project选项为项目 slug。 查看有关--project的文档以获取更多详情。 (例如:--project project-abc4567-wxyz123456789) - 设置
--branch选项为功能分支名称。 查看有关--branch的文档以获取完整概述。 (例如:--branch feature-branch) - 为
feature-branch分支设置起始点:- 将
--start-point选项设置为功能分支的起始点。 查看有关--start-point的文档以获取完整概述。 (例如:--start-point main) - 设置
--start-point-hash选项为功能分支起始点的git哈希。 查看有关--start-point-hash的文档以获取完整概述。 (例如:--start-point-hash 32ae...dd8b) - 设置
--start-point-clone-thresholds标志以从起始点克隆阈值。 查看有关--start-point-clone-thresholds的文档以获取完整概述。 (例如:--start-point-clone-thresholds) - 设置
--start-point-reset标志以始终将分支重置为起始点。 这将防止基准测试数据漂移。 查看有关--start-point-reset的文档以获取完整概述。 (例如:--start-point-reset)
- 将
- 将
--testbed选项设置为测试台名称。 查看有关--tested的文档以获取更多详情。 (例如:--testbed ci-runner) - 设置
--err标志以在生成警报时让命令失败。 查看关于--err的文档以获取完整概述。 (例如:--err) - 设置
--adapter选项为由bencher mock生成的Bencher Metric Format JSON(json)。 查看基准测试工具适配器以获取完整概述。 (例如:--adapter json) - 指定基准测试命令参数。
查看基准测试命令以获取完整概述。
(例如:
bencher mock)
第一次在 CI 中运行此命令时,
Bencher 将创建feature-branch分支,因为它尚不存在。
新的feature-branch将使用main分支
在哈希32aea434d751648726097ed3ac760b57107edd8b作为其起始点。
这意味着feature-branch将具有main分支的所有数据和阈值的副本,以便将bencher mock的结果进行比较。
在所有后续运行中,Bencher 将重置feature-branch分支为起始点,
并使用main分支数据和阈值来检测性能回归。
相对持续基准测试
在快速开始和Docker 自托管教程中到此为止,让我们为我们的claimed项目添加相对持续基准测试。
🐰 确保您已创建 API 令牌并将其设置为
BENCHER_API_TOKEN环境变量后再继续!
相对持续基准测试并排比较两版代码。这在处理噪声很大的 CI/CD 环境时会很有用,在这些环境中,可用资源在每次运行之间可能会有很大差异。在本例中,我们将比较在main分支上运行的结果与在特性分支上运行的结果,这个特性分支被贴切地命名为feature-branch。由于每个 CI 环境都有所不同,以下示例旨在说明而非实用。如需更具体的示例,请参阅GitHub Actions 中的持续基准测试以及GitLab CI/CD 中的持续基准测试。
首先,我们需要在 CI 中用git检出main分支:
git checkout main然后我们需要在 CI 中运行我们在main分支上的基准测试:
bencher run \--project project-abc4567-wxyz123456789 \--branch main \--start-point-reset \--testbed ci-runner \--adapter json \bencher mock- 使用
bencher runCLI 子命令运行您的main分支基准测试。有关完整概述,请参阅bencher runCLI 子命令。(例如:bencher run) - 将
--project选项设置为项目标识符。有关详细信息,请参阅--project文档。(例如:--project project-abc4567-wxyz123456789) - 将
--branch选项设置为基础分支名称。有关完整概述,请参阅--branch文档。(例如:--branch main) - 设置
--start-point-reset标志以始终重置基础分支。这将确保所有基准数据均来自当前 CI 运行器。有关完整概述,请参阅--start-point-reset文档。(例如:--start-point-reset) - 将
--testbed选项设置为 CI 运行器测试平台名称。有关详细信息,请参阅--testbed文档。(例如:--testbed ci-runner) - 将
--adapter选项设置为由bencher mock生成的Bencher Metric Format JSON(json)。 有关完整概述,请参阅基准测试适配器。(例如:--adapter json) - 指定基准命令参数。有关完整概述,请参阅基准命令。(例如:
bencher mock)
在 CI 中第一次运行此命令时,将创建main分支,因为它尚不存在。新创建的main将没有起始点、现有数据或阈值。在后续运行中,旧的main Head 将被替换,并创建新的main Head,不含起始点、现有数据或阈值。
接下来,我们需要在 CI 中用git检出feature-branch分支:
git checkout feature-branch最后,我们准备在 CI 中运行我们的feature-branch基准测试:
bencher run \--project project-abc4567-wxyz123456789 \--branch feature-branch \--start-point main \--start-point-reset \--testbed ci-runner \--threshold-measure latency \--threshold-test percentage \--threshold-upper-boundary 0.25 \--thresholds-reset \--err \--adapter json \bencher mock- 使用
bencher runCLI 子命令运行您的feature-branch基准测试。有关完整概述,请参阅bencher runCLI 子命令。(例如:bencher run) - 将
--project选项设置为项目标识符。有关详细信息,请参阅--project文档。(例如:--project project-abc4567-wxyz123456789) - 将
--branch选项设置为特性分支名称。有关完整概述,请参阅--branch文档。(例如:--branch feature-branch) - 设置
feature-branch分支的起始点:- 将
--start-point选项设置为特性分支起始点。有关完整概述,请参阅--start-point文档。(例如:--start-point main) - 设置
--start-point-reset标志以始终将分支重置为起始点。这将仅使用最新的相对基准结果。有关完整概述,请参阅--start-point-reset文档。(例如:--start-point-reset)
- 将
- 将
--testbed选项设置为 CI 运行器测试平台名称。有关详细信息,请参阅--testbed文档。(例如:--testbed ci-runner) - 设置
feature-branch分支、ci-runner测试平台和latency测量的阈值:- 将
--threshold-measure选项设置为由bencher mock生成的内置latency测量。有关详细信息,请参阅--threshold-measure文档。(例如:--threshold-measure latency) - 将
--threshold-test选项设置为基本百分比(percentage)。有关完整概述,请参阅--threshold-test文档。(例如:--threshold-test percentage) - 将
--threshold-upper-boundary选项设置为上限0.25。有关详细信息,请参阅--threshold-upper-boundary文档。(例如:--threshold-upper-boundary 0.25) - 设置
--thresholds-reset标志,以便仅激活指定的阈值。有关完整概述,请参阅--thresholds-reset文档。(例如:--thresholds-reset)
- 将
- 设置
--err标志以便在生成警报时命令失败。有关完整概述,请参阅--err文档。(例如:--err) - 将
--adapter选项设置为由bencher mock生成的Bencher Metric Format JSON(json)。有关完整概述,请参阅基准测试适配器。(例如:--adapter json) - 指定基准命令参数。有关完整概述,请参阅基准命令。(例如:
bencher mock)
每次在 CI 中运行此命令时,它都将feature-branch的结果与main的最新结果进行比较。然后使用指定的阈值检测性能回归。
变更点检测
变更点检测使用变更点算法来评估最近结果的大窗口。这使得算法能够忽略异常值作为噪声,从而产生更少的误报。尽管变更点检测被认为是持续性基准测试,但它不允许您在CI中检测性能回归。也就是说,您无法在功能分支合并之前检测到性能回归。这有时称为“带外”检测。
例如,如果您有一个基准 bench_my_critical_path,并且它具有以下历史延迟:5 ms,6 ms,5 ms,5ms,7ms。
如果下一个基准结果是 11 ms,那么统计持续基准测试阈值和变更点检测算法将会做出非常不同的解读。阈值可能会被超出并生成警报。如果这个基准运行与一个拉取请求绑定在一起,构建可能会因为这个警报而失败。然而,变更点算法暂时不会做任何事情。如果下一次运行结果下降回 5 ms,则可能不会生成警报。相反,如果接下来的运行结果是 10 ms 和 12 ms,那么只有这时变更点算法才会触发警报。
您对在 Bencher 中使用变更点检测感兴趣吗?如果是这样,请在跟踪问题上留下评论或直接联系我们。
🐰 恭喜!您已经学会了如何使用 Bencher 在 CI 中跟踪基准测试!🎉