You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Google Benchmark复现std::list与std::vector头部插入性能遇阻

如何改进Google Benchmark代码复现std::list与std::vector头部插入性能结论?

原始性能结论(来自CppCon 2022)

  • std::list头部插入的耗时呈线性增长
  • std::vector头部插入的耗时呈多项式增长
  • 元素数量较少(<800)时,std::vector性能优于std::list

你的测试代码

#include <benchmark/benchmark.h>

static void bm_vec(benchmark::State &state) {
    for (auto _ : state)
    {
        state.PauseTiming();
        std::vector<int> v ;
        benchmark::DoNotOptimize(v.data());
        state.ResumeTiming();
        for (int i = 0; i < state.range(0); i++)
        {
           v.insert(v.begin(), 1);
        }
        benchmark::ClobberMemory();
    }
}

BENCHMARK(bm_vec)->DenseRange(10,2000,10);

static void bm_list(benchmark::State &state) {
    
    for (auto _ : state)
    {
        state.PauseTiming();
        std::list<int> v ;
        benchmark::DoNotOptimize(v.front());
        state.ResumeTiming();
        for (int i = 0; i < state.range(0); i++)
        {
            v.insert(v.begin(), 1);
        }
        
    }
}
BENCHMARK(bm_list)->DenseRange(10,2000,10);

BENCHMARK_MAIN();

代码问题与改进方案

1. 修复std::list的未定义行为与优化屏障错误

你的bm_list测试中,空std::list调用v.front()会触发未定义行为(空列表没有首元素),且DoNotOptimize的使用没有正确阻止编译器优化掉无意义的list操作。

修改方式:

  • 移除v.front()调用,改为对list对象本身设置优化屏障:benchmark::DoNotOptimize(&v);
  • 在list测试末尾添加benchmark::ClobberMemory();,确保编译器不会忽略list的内存修改操作。

2. 优化vector测试的内存屏障有效性

当前vector测试的ClobberMemory()位置可以保留,但要确保DoNotOptimize(v.data())持续生效——它能阻止编译器将vector的内存操作优化为无意义的代码。

3. 确保容器初始化完全脱离计时区间

当前的PauseTiming和ResumeTiming使用逻辑正确,但需确认初始化容器的代码完全落在暂停计时的区间内,避免初始化开销干扰测试结果。

改进后的完整代码

#include <benchmark/benchmark.h>
#include <vector>
#include <list>

static void bm_vec(benchmark::State &state) {
    for (auto _ : state)
    {
        state.PauseTiming();
        std::vector<int> v;
        benchmark::DoNotOptimize(v.data());
        state.ResumeTiming();
        
        for (int i = 0; i < state.range(0); ++i) {
            v.insert(v.begin(), 1);
        }
        
        benchmark::ClobberMemory();
    }
}
BENCHMARK(bm_vec)->DenseRange(10, 2000, 10);

static void bm_list(benchmark::State &state) {
    for (auto _ : state)
    {
        state.PauseTiming();
        std::list<int> v;
        benchmark::DoNotOptimize(&v); // 对list对象设置优化屏障
        state.ResumeTiming();
        
        for (int i = 0; i < state.range(0); ++i) {
            v.insert(v.begin(), 1);
        }
        
        benchmark::ClobberMemory(); // 确保内存修改被编译器观测到
    }
}
BENCHMARK(bm_list)->DenseRange(10, 2000, 10);

BENCHMARK_MAIN();

额外优化建议

  • 添加->UseRealTime()到基准测试配置,避免CPU频率缩放影响结果:
    BENCHMARK(bm_vec)->DenseRange(10,2000,10)->UseRealTime();
    BENCHMARK(bm_list)->DenseRange(10,2000,10)->UseRealTime();
    
  • 运行测试时关闭后台程序,确保系统资源充足,减少测试波动。

内容的提问来源于stack exchange,提问作者orfvl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 09:05:16