Skip to content

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 多次运行取平均值,减少噪音。

系统学习 C++ 生态,深入底层架构