基准测试#
设置#
首先安装 Archery 工具来运行基准测试套件。
运行基准测试套件#
可以使用 benchmark run 子命令运行基准测试套件。
# Run benchmarks in the current git workspace
archery benchmark run
# Storing the results in a file
archery benchmark run --output=run.json
有时需要传递自定义的 CMake 标志,例如:
export CC=clang-8 CXX=clang++8
archery benchmark run --cmake-extras="-DARROW_SIMD_LEVEL=NONE"
此外,还可以指定完整的 CMake 构建目录。
archery benchmark run $HOME/arrow/cpp/release-build
比较#
基准测试的目标之一是检测性能回归。为此,archery 通过 benchmark diff 子命令实现了基准测试比较功能。
在默认调用中,它会将当前源码(在 git 中称为当前工作区)与本地 main 分支进行比较。
archery --quiet benchmark diff --benchmark-filter=FloatParsing
-----------------------------------------------------------------------------------
Non-regressions: (1)
-----------------------------------------------------------------------------------
benchmark baseline contender change % counters
FloatParsing<FloatType> 105.983M items/sec 105.983M items/sec 0.0 {}
------------------------------------------------------------------------------------
Regressions: (1)
------------------------------------------------------------------------------------
benchmark baseline contender change % counters
FloatParsing<DoubleType> 209.941M items/sec 109.941M items/sec -47.632 {}
欲了解更多信息,请调用 archery benchmark diff --help 命令查看多种调用示例。
高效迭代#
由于构建和运行时间较长,基准测试开发过程可能会很繁琐。使用 archery benchmark diff 时可以利用多种技巧来减少这种开销。
首先,基准测试命令支持比较现有的构建目录。这可以与 --preserve 标志配合使用,以避免从零开始重新构建源代码。
# First invocation clone and checkouts in a temporary directory. The
# directory is preserved with --preserve
archery benchmark diff --preserve
# Modify C++ sources
# Re-run benchmark in the previously created build directory.
archery benchmark diff /tmp/arrow-bench*/{WORKSPACE,master}/build
其次,基准测试的运行结果可以保存为 JSON 文件。这不仅避免了重新构建源代码,还避免了执行(有时很耗时的)基准测试。这种技术可以作为一种简易的缓存机制使用。
# Run the benchmarks on a given commit and save the result
archery benchmark run --output=run-head-1.json HEAD~1
# Compare the previous captured result with HEAD
archery benchmark diff HEAD run-head-1.json
第三,基准测试命令支持过滤套件(--suite-filter)和基准测试(--benchmark-filter),这两个选项都支持正则表达式。
# Taking over a previous run, but only filtering for benchmarks matching
# `Kernel` and suite matching `compute-aggregate`.
archery benchmark diff \
--suite-filter=compute-aggregate --benchmark-filter=Kernel \
/tmp/arrow-bench*/{WORKSPACE,master}/build
在进行比较时,不需要重新运行基准测试,可以为竞品(contender)和/或基准(baseline)指定一个 JSON 文件(由 archery benchmark run 生成)。
archery benchmark run --output=baseline.json $HOME/arrow/cpp/release-build
git checkout some-feature
archery benchmark run --output=contender.json $HOME/arrow/cpp/release-build
archery benchmark diff contender.json baseline.json
回归检测#
编写基准测试#
基准测试命令默认会使用正则表达式
^Regression对基准测试进行过滤。这样默认情况下不会运行所有基准测试。因此,如果您希望自动验证基准测试的回归情况,名称必须符合该正则表达式。为了保证统计显著性,基准测试命令将使用
--benchmark_repetitions=K选项运行。因此,基准测试不应在(C++)基准测试的参数定义中覆盖重复次数。基于第 2 点,基准测试应该运行得足够快。通常,当输入数据无法放入缓存(L2/L3)时,基准测试将受限于内存带宽而非 CPU。在这种情况下,可以减小输入规模。
默认情况下,Google 的 benchmark 库会使用 cputime 指标,即进程所有线程在 CPU 上占用的运行时间之和。与之相对的是 realtime(挂钟时间),即 end_time - start_time 的差值。在单线程模型中,推荐使用 cputime,因为它较少受上下文切换影响。在多线程场景下,cputime 会因为线程数量的增加而被放大,从而偏离 realtime,导致结果不准确。因此,如果是多线程基准测试,最好使用
SetRealtime(),请参阅此 示例。
脚本化#
archery 是作为一个带有命令行前端的 Python 库编写的。可以导入该库来自动执行某些任务。
由于构建输出,命令行界面的一些调用可能会非常冗长。可以使用 --quiet 选项来控制/避免这种情况,或者使用 --output=<file>,例如:
archery benchmark diff --benchmark-filter=Kernel --output=compare.json ...