在C++项目里,当我们怀疑某个函数存在性能瓶颈,或者想确认两种实现方式谁更优时,不能仅凭经验下结论。函数性能分析的核心在于用可重复、可量化的方式测量耗时,而基准测试正是达成这一目标的重要手段。通过对比不同函数在相同条件下的表现,我们能做出客观的工程决策。

为什么需要基准测试
简单用时钟算一下时间看似方便,但很容易掉进陷阱。编译器可能会把没用的计算优化掉,操作系统也会把CPU时间分给别的进程。基准测试框架会尽量排除这些干扰,让结果更接近真实情况。
使用chrono做基础计时
如果不想引入第三方库,可以用标准库的<chrono>手动写一个小基准。下面例子对比两种求和方式的耗时:
#include <iostream>
#include <chrono>
#include <vector>
// 方式一:普通循环求和
long long sum_normal(const std::vector<int>& v) {
long long s = 0;
for (int x : v) s += x;
return s;
}
// 方式二:使用accumulate
#include <numeric>
long long sum_acc(const std::vector<int>& v) {
return std::accumulate(v.begin(), v.end(), 0LL);
}
int main() {
std::vector<int> data(100000, 1);
// 预热,避免首次运行受系统影响
volatile auto warm = sum_normal(data);
auto t1 = std::chrono::steady_clock::now();
for (int i = 0; i < 1000; ++i) {
volatile auto r = sum_normal(data);
}
auto t2 = std::chrono::steady_clock::now();
auto t3 = std::chrono::steady_clock::now();
for (int i = 0; i < 1000; ++i) {
volatile auto r = sum_acc(data);
}
auto t4 = std::chrono::steady_clock::now();
std::cout << "normal: "
<< std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count()
<< " msn";
std::cout << "accumulate: "
<< std::chrono::duration_cast<std::chrono::milliseconds>(t4 - t3).count()
<< " msn";
return 0;
}
这里用volatile防止编译器把计算结果优化掉,并且做了预热。不过手动写法要自己处理迭代次数和统计,不够严谨。
使用Google Benchmark框架
Google Benchmark是C++里常用的基准测试库,它会自动决定迭代次数并给出均值和标准差。下面是用它比较两个函数的示例:
#include <benchmark/benchmark.h>
#include <vector>
#include <numeric>
static std::vector<int> make_data() {
return std::vector<int>(100000, 1);
}
static void BM_SumNormal(benchmark::State& state) {
auto data = make_data();
for (auto _ : state) {
long long s = 0;
for (int x : data) s += x;
benchmark::DoNotOptimize(s);
}
}
BENCHMARK(BM_SumNormal);
static void BM_SumAcc(benchmark::State& state) {
auto data = make_data();
for (auto _ : state) {
auto r = std::accumulate(data.begin(), data.end(), 0LL);
benchmark::DoNotOptimize(r);
}
}
BENCHMARK(BM_SumAcc);
BENCHMARK_MAIN();
编译运行后,框架会输出每张表的耗时分布,方便我们直接比较。使用benchmark::DoNotOptimize可以阻止编译器消除被测代码。
写基准测试的注意事项
- 保持输入规模一致,且数据应提前准备好,避免构造过程计入耗时。
- 使用
DoNotOptimize或volatile防止死代码消除。 - 多次运行取统计值,不要只看一次结果。
- 关闭调试模式,使用Release编译选项,否则测出的不是真实性能。
小结
用C++做函数性能比较时,基准测试比拍脑袋准确得多。小场景可用chrono快速验证,严肃的性能分析建议上Google Benchmark。只要控制好变量、防止过度优化,就能得到可信的数据来指导代码优化。