Saltar a contenido

Última actualización:2026-10-12

Pruebas de rendimiento con Google Benchmark

《C++那些事》: empieza tus pruebas con BenchMark

0. Introducción

Objetivo de esta sección: ¡completar un pequeño proyecto de BenchMark!

En el desarrollo cotidiano, ¿cómo medir el rendimiento de tus propias interfaces? ¿Cómo montar rápidamente en C++ un framework de pruebas BenchMark?

En esta sección abriremos, paso a paso, la primera lección de introducción a BenchMark.

1. Estructura del proyecto

Tomamos como ejemplo la inserción en vector y list para explicar el proyecto BenchMark.

Este proyecto se gestiona con Bazel; si aún no sabes configurar el entorno correspondiente, consulta los cursos en vídeo y la documentación anteriores.

Crea una estructura de proyecto como esta:


BenchMark usa el proyecto de código abierto de google:

https://github.com/google/benchmark.git

Antes, cuando usabais bibliotecas de terceros, había que compilar el código fuente uno mismo, generar la biblioteca so y luego enlazarla: ¡demasiado lío! Aquí, al gestionarlo directamente con bazel, basta con añadir el proyecto git de la dependencia en el WORKSPACE; por ejemplo, aquí se usa la versión v1.7.1 de google benchmark.

git_repository(
    name = "google_benchmark",
    remote = "https://github.com/google/benchmark.git",
    tag = "v1.7.1",
)

A continuación debemos implementar la lógica principal: crea un directorio src y añade dentro un archivo BUILD con el objetivo de compilar los cpp anteriores. Nota: aquí se depende de la biblioteca benchmark y su forma de uso es @el name configurado antes//:benchmark

cc_binary(
    name = "vector_list",
    srcs = ["vector_list.cc"],
    deps = [
        "@google_benchmark//:benchmark",
    ]
)

De este modo, ya se puede usar en el archivo cc:

#include <benchmark/benchmark.h>

2. Demo

Escribe dos funciones de inserción; es muy sencillo. El marco es el que se muestra a continuación, con algunos puntos que conviene explicar:

  • state es la información de estado en tiempo de ejecución de benchmark
  • Por ejemplo: control de suspensión, control de parámetros de entrada, etc.
  • state.range(0) obtiene justamente el parámetro 0
  • DoNotOptimize indica no aplicar optimizaciones del compilador
// 测试 std::vector 的插入速度
static void BM_vectorInsert(benchmark::State& state) {
    for (auto _ : state) {
        std::vector<int> v;
        for (size_t i = 0; i < state.range(0); ++i) {
            v.insert(v.begin() + i, i);
        }
        benchmark::DoNotOptimize(v);
    }
}

// 测试 std::list 的插入速度
static void BM_listInsert(benchmark::State& state) {
    for (auto _ : state) {
        std::list<int> l;
        for (size_t i = 0; i < state.range(0); ++i) {
            l.insert(l.begin(), i);
        }
        benchmark::DoNotOptimize(l);
    }
}

La llamada desde la entrada principal:

  • Range(8, 8 << 10) significa empezar en 8 y multiplicar por 8 cada vez hasta 8192; esto corresponde al state.range(0) anterior, y ese número se pasa como parámetro
  • BENCHMARK_MAIN indica que se usa la función main de google benchmark; sabemos que todo ejecutable tiene un main, y la razón de que este archivo sea ejecutable es que esta macro, tras expandirse, es la función main. ¿Lo has aprendido?
// 定义基准测试
BENCHMARK(BM_vectorInsert)->Range(8, 8<<10);
BENCHMARK(BM_listInsert)->Range(8, 8<<10);

// 运行基准测试
BENCHMARK_MAIN();

3. Resumen

En esta sección hemos aprendido paso a paso google benchmark y lo hemos aplicado a nuestro propio proyecto; puedes hacer muchas cosas interesantes con él. El código fuente de esta sección se ha puesto en la comunidad 知识星球 para que lo estudiéis; únete para intercambiar ideas~

Temas relacionados

Comentarios