Google Benchmark 使用详解

2018-10-22 language c/cpp

Google 提供的 Benchmark 工具是一款强大的性能压测工具,易于安装和使用,并提供了全面的性能测试接口。

示例

$ cat CMakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
PROJECT(hello)
SET(SRC_LIST main.cpp)
LINK_DIRECTORIES(/svr/third/installed/lib64)
INCLUDE_DIRECTORIES(/svr/third/installed/include)
ADD_EXECUTABLE(hello ${SRC_LIST})
TARGET_LINK_LIBRARIES(hello benchmark pthread)

$ cat main.cpp
#include <string>
#include <sstream>

#include <benchmark/benchmark.h>

std::string uint2str(unsigned int num)
{
        std::ostringstream oss;
        oss << num;
        return oss.str();
}

static void BM_uint2str(benchmark::State& state)
{
        unsigned int num = 1234;
        while (state.KeepRunning())
                uint2str(num);
}

BENCHMARK(BM_uint2str);

BENCHMARK_MAIN();

然后直接编译即可。

Running ./hello
Run on (8 X 2800 MHz CPU s)
CPU Caches:
  L1 Data 48 KiB (x4)
  L1 Instruction 32 KiB (x4)
  L2 Unified 1280 KiB (x4)
  L3 Unified 58368 KiB (x1)
Load Average: 4.00, 4.02, 4.03
------------------------------------------------------
Benchmark            Time             CPU   Iterations
------------------------------------------------------
BM_uint2str        332 ns          330 ns      2213145

其中各个字段的含义如下:

  • Time 真正运行时间,也就是从开始执行到完成的墙上时钟 (Wall Clock) 时间,包括切换到其它进程使用的时间片以及本进程因为 IO 等阻塞时间。
  • CPU 执行用户进程操作和内核系统调用所消耗时间总和,也包括子进程的开销。
  • Iterations 函数执行的次数,执行次数越多说明函数性能越好。

使用详解

README.md 中的内容不多,一些比较核心的东西可以参考源码 docs 目录下的内容。

所有的测试用例串行执行。

循环次数

通过 Iterations 和 Repetitions 决定总的执行次数,对于具体函数来说示例如下。

static void BM_uint2str(benchmark::State& state) // Repetitions(1)
{
    unsigned int num = 1234;
    while (state.KeepRunning()) // Iterations
        uint2str(num);
}

其中 Repetitions 默认为 1,而 Iterations 是动态的,会根据前几次的运行情况大致估算执行次数从而可以得到相对稳定的结果,一般耗时越长执行的次数越少,最少一次最大 1e9 次。

可以通过 --benchmark_repetitions=4 参数指定,此时默认会同时打印一些统计信息,可用 --benchmark_report_aggregates_only 参数关闭。

另外,还可以通过 BENCHMARK(BM_uint2str)->Repetitions(3)->Iterations(2); 指定,相比参数来说优先级更高。

传入参数

有时可以配置不同的参数。

static void BM_uint2str(benchmark::State& state) // Repetitions(1)
{
    auto num = state.range(0);
    while (state.KeepRunning()) // Iterations
        uint2str(num);
}
BENCHMARK(BM_uint2str)->Arg(0)->Arg(5);

也可以指定范围,默认是 2 的基数,如下指定基数为 10,同时设置了范围。

BENCHMARK(BM_uint2str)->RangeMultiplier(10)->Range(10, 1000);

命令行参数

  • --benchmark_filter 过滤指定的压测,例如 BM_uint2str

参考

  • Github Benchmark 官方源码,在 docs 目录下有很多相关的文档。
  • Quick Bench 一个不错的页面显示,可以用于简单的测试用例性能比较。