Google Benchmark — 性能测试
Google Benchmark 是 C++ 微基准测试的标准工具,自动处理预热、统计、防止编译器优化,输出专业的性能报告。
安装
bash
# vcpkg
vcpkg install benchmark
# CMake
find_package(benchmark REQUIRED)
target_link_libraries(bench PRIVATE benchmark::benchmark)基本用法
cpp
#include <benchmark/benchmark.h>
#include <vector>
#include <algorithm>
// 基本基准测试
static void BM_VectorPushBack(benchmark::State& state) {
for (auto _ : state) { // 自动运行足够多次
std::vector<int> v;
for (int i = 0; i < state.range(0); ++i) {
v.push_back(i);
}
benchmark::DoNotOptimize(v); // 防止编译器优化掉
}
}
BENCHMARK(BM_VectorPushBack)->Range(8, 8 << 10); // 8 到 8192
// 带参数的基准测试
static void BM_Sort(benchmark::State& state) {
std::vector<int> data(state.range(0));
std::iota(data.begin(), data.end(), 0);
std::shuffle(data.begin(), data.end(), std::mt19937{42});
for (auto _ : state) {
auto copy = data; // 每次排序新副本
std::sort(copy.begin(), copy.end());
benchmark::DoNotOptimize(copy);
}
state.SetComplexityN(state.range(0)); // 用于复杂度分析
}
BENCHMARK(BM_Sort)
->RangeMultiplier(2)
->Range(64, 1 << 16)
->Complexity(benchmark::oNLogN);
BENCHMARK_MAIN();对比测试
cpp
// 对比不同实现的性能
static void BM_MapFind(benchmark::State& state) {
std::map<int, int> m;
for (int i = 0; i < 1000; ++i) m[i] = i;
for (auto _ : state) {
auto it = m.find(state.range(0) % 1000);
benchmark::DoNotOptimize(it);
}
}
static void BM_UnorderedMapFind(benchmark::State& state) {
std::unordered_map<int, int> m;
for (int i = 0; i < 1000; ++i) m[i] = i;
for (auto _ : state) {
auto it = m.find(state.range(0) % 1000);
benchmark::DoNotOptimize(it);
}
}
static void BM_AbslFlatHashMapFind(benchmark::State& state) {
absl::flat_hash_map<int, int> m;
for (int i = 0; i < 1000; ++i) m[i] = i;
for (auto _ : state) {
auto it = m.find(state.range(0) % 1000);
benchmark::DoNotOptimize(it);
}
}
BENCHMARK(BM_MapFind)->Arg(42);
BENCHMARK(BM_UnorderedMapFind)->Arg(42);
BENCHMARK(BM_AbslFlatHashMapFind)->Arg(42);高级特性
cpp
// 自定义计数器
static void BM_Throughput(benchmark::State& state) {
std::vector<int> data(state.range(0));
size_t bytes_processed = 0;
for (auto _ : state) {
process(data);
bytes_processed += data.size() * sizeof(int);
}
state.SetBytesProcessed(bytes_processed); // 显示吞吐量 MB/s
state.SetItemsProcessed(state.iterations() * data.size()); // 显示 items/s
state.counters["items"] = benchmark::Counter(
state.iterations(), benchmark::Counter::kIsRate);
}
// 多线程基准测试
static void BM_MultiThread(benchmark::State& state) {
for (auto _ : state) {
// 每个线程执行这里的代码
benchmark::DoNotOptimize(compute());
}
}
BENCHMARK(BM_MultiThread)->Threads(1)->Threads(2)->Threads(4)->Threads(8);
// Setup/Teardown
static void BM_WithSetup(benchmark::State& state) {
// Setup(只执行一次)
auto data = prepare_data(state.range(0));
for (auto _ : state) {
benchmark::DoNotOptimize(process(data));
}
// Teardown(只执行一次)
cleanup(data);
}运行与输出
bash
# 运行所有基准测试
./bench
# 过滤
./bench --benchmark_filter="BM_Sort"
# 输出格式
./bench --benchmark_format=json --benchmark_out=results.json
./bench --benchmark_format=csv --benchmark_out=results.csv
# 重复运行(统计方差)
./bench --benchmark_repetitions=5 --benchmark_report_aggregates_only=true
# 与基准比较(需要 compare.py)
./bench --benchmark_out=new.json
python3 compare.py benchmarks old.json new.json# 输出示例
Benchmark Time CPU Iterations
-------------------------------------------------------
BM_MapFind/42 156 ns 156 ns 4480000
BM_UnorderedMapFind/42 45 ns 45 ns 15600000
BM_AbslFlatHashMapFind/42 28 ns 28 ns 25000000关键认知
benchmark::DoNotOptimize(x) 防止编译器优化掉被测代码,benchmark::ClobberMemory() 强制刷新内存。基准测试要在 Release 模式下运行(-O2/-O3),Debug 模式的结果没有意义。用 --benchmark_repetitions 多次运行取平均值,减少噪音。