Google Benchmark是一个强大的C++微基准测试库,专门用于测量和比较代码片段的性能。下面详细介绍如何使用它进行性能测试。
1. 安装Google Benchmark
Linux/macOS安装
# 使用包管理器安装(如Ubuntu)
sudo apt-get install libbenchmark-dev libbenchmark1# 或者从源码安装
git clone https://github.com/google/benchmark.git
cd benchmark
cmake -E make_directory "build"
cmake -E chdir "build" cmake -DBENCHMARK_DOWNLOAD_DEPENDENCIES=on -DCMAKE_BUILD_TYPE=Release ../
cmake --build "build" --config Release
sudo cmake --build "build" --config Release --target install
Windows安装
使用vcpkg:
vcpkg install benchmark
2. 基本用法
简单基准测试示例
#include <benchmark/benchmark.h>static void BM_StringCreation(benchmark::State& state) {for (auto _ : state) {std::string empty_string;}
}
BENCHMARK(BM_StringCreation);static void BM_StringCopy(benchmark::State& state) {std::string x = "hello";for (auto _ : state) {std::string copy(x);}
}
BENCHMARK(BM_StringCopy);BENCHMARK_MAIN();
编译命令
g++ mybenchmark.cpp -std=c++11 -lbenchmark -lpthread -o mybenchmark
3. 关键特性
参数化基准测试
static void BM_SetInsert(benchmark::State& state) {std::set<int> data;for (auto _ : state) {state.PauseTiming(); // 暂停计时// 准备数据(不计时)for (int i = 0; i < state.range(0); ++i)data.insert(i);state.ResumeTiming(); // 恢复计时// 要测试的操作data.insert(state.range(0));}
}
// 测试不同大小的输入:8, 64, 512, 4k, 8k
BENCHMARK(BM_SetInsert)->RangeMultiplier(8)->Range(8, 8<<10);
自定义计数器
static void BM_UserCounters(benchmark::State& state) {double numFoos = 0, numBars = 0, numBazs = 0;for (auto _ : state) {// ... 执行操作 ...numFoos += 1.0;numBars += 2.0;numBazs += 3.0;}state.counters["Foo"] = numFoos;state.counters["Bar"] = numBars;state.counters["Baz"] = numBazs;
}
BENCHMARK(BM_UserCounters);
4. 高级功能
多线程基准测试
static void BM_OpenMP(benchmark::State& state) {int sum = 0;for (auto _ : state) {#pragma omp parallel for reduction(+:sum)for (int i = 0; i < 1000000; ++i) {sum += i;}}
}
BENCHMARK(BM_OpenMP)->UseRealTime()->Threads(2)->Threads(4);
复杂设置和清理
class MyFixture : public benchmark::Fixture {
public:void SetUp(const benchmark::State& state) override {// 测试前设置data.resize(state.range(0));std::generate(data.begin(), data.end(), std::rand);}void TearDown(const benchmark::State&) override {// 测试后清理data.clear();}std::vector<int> data;
};BENCHMARK_DEFINE_F(MyFixture, BM_TestSort)(benchmark::State& state) {for (auto _ : state) {std::sort(data.begin(), data.end());}
}
BENCHMARK_REGISTER_F(MyFixture, BM_TestSort)->Range(8, 8<<10);
5. 运行和分析结果
运行基准测试
./mybenchmark
常用选项
-
--benchmark_filter=<regex>
: 只运行匹配的测试 -
--benchmark_repetitions=<num>
: 重复运行次数 -
--benchmark_report_aggregates_only=true
: 只显示统计结果 -
--benchmark_format=<console|json|csv>
: 输出格式 -
--benchmark_out=<filename>
: 输出到文件
结果示例
---------------------------------------------------------------------
Benchmark Time CPU Iterations UserCounters...
---------------------------------------------------------------------
BM_StringCreation 5 ns 5 ns 135789473
BM_StringCopy 12 ns 12 ns 57692308
BM_SetInsert/8 18 ns 18 ns 38888889
BM_SetInsert/64 25 ns 25 ns 28000000
BM_SetInsert/512 112 ns 112 ns 6400000
6. 最佳实践
-
足够大的迭代次数:确保每个测试运行足够长时间(通常1秒以上)
-
避免优化干扰:确保编译器没有优化掉你要测试的代码
-
隔离测试:每次测试只测量一个特定操作
-
多次运行:使用
--benchmark_repetitions
检测结果稳定性 -
考虑缓存效应:大内存操作可能需要特殊处理
通过Google Benchmark,你可以获得精确、可重复的性能测量结果,帮助优化你的C++代码。