Ir para o conteúdo

Última atualização:2026-10-12

Testes de performance com Google Benchmark

C++那些事: comece seus testes de BenchMark

0.Introdução

Objetivo desta seção: completar um pequeno projeto de BenchMark!

No dia a dia de desenvolvimento, como testar o desempenho das suas interfaces? Como montar rapidamente um framework de testes de BenchMark em C++?

Esta seção abre, passo a passo (Step By Step), a primeira lição de introdução ao BenchMark.

1.Estrutura do projeto

Usaremos como exemplo a inserção em vector e list para explicar o projeto de BenchMark.

Desta vez o projeto é gerenciado com Bazel; se você ainda não sabe como configurar o ambiente relacionado, consulte os cursos em vídeo/documentação anteriores.

Crie uma estrutura de projeto:


O BenchMark usa o projeto open source do google:

https://github.com/google/benchmark.git
Como antes, quando você usava uma biblioteca de terceiros, precisava compilar o código-fonte, gerar a biblioteca so e depois vinculá-la — trabalhoso demais! Aqui, usando o bazel diretamente, basta adicionar o projeto git da dependência no WORKSPACE; por exemplo, aqui é usada a versão v1.7.1 do google benchmark.

git_repository(
    name = "google_benchmark",
    remote = "https://github.com/google/benchmark.git",
    tag = "v1.7.1",
)
Em seguida, precisamos implementar a lógica principal: crie um diretório src e adicione um arquivo BUILD nele, com o objetivo de compilar os arquivos cpp mencionados. Observação: aqui há dependência da biblioteca benchmark, e a forma de usá-la é @o name configurado acima//:benchmark

cc_binary(
    name = "vector_list",
    srcs = ["vector_list.cc"],
    deps = [
        "@google_benchmark//:benchmark",
    ]
)
Assim, já é possível usar no arquivo cc:

#include <benchmark/benchmark.h>

2.Parte da Demo

Escreva duas funções de inserção, bem simples; o framework é o mostrado abaixo, com alguns pontos que merecem explicação:

  • state é a informação de estado em tempo de execução do benchmark
  • por exemplo: controle de suspensão, controle dos parâmetros de entrada etc.
  • state.range(0) obtém o parâmetro de índice 0
  • DoNotOptimize indica não fazer otimização do 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);
    }
}
Chamada no ponto de entrada principal:

  • Range(8, 8 << 10) significa começar em 8, multiplicando por 8 a cada vez, até 8192; isso corresponde ao state.range(0) acima, e esse número é passado como parâmetro
  • BENCHMARK_MAIN indica usar a função main do google benchmark; sabemos que todo executável tem um main, e a razão de esse arquivo poder ser executado é que essa macro, ao ser expandida, é a função main. Você entendeu?
// 定义基准测试
BENCHMARK(BM_vectorInsert)->Range(8, 8<<10);
BENCHMARK(BM_listInsert)->Range(8, 8<<10);

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

3.Conclusão

Nesta seção, aprendemos passo a passo o google benchmark e o aplicamos ao nosso próprio projeto, no qual você pode fazer muitas coisas interessantes. O código-fonte desta seção foi colocado na planeta de conhecimento para todos estudarem; junte-se a nós para trocar experiências~

Tópicos relacionados

Comentários