CMake and Google benchmark

Posted by chunyang on December 21, 2024
TAGS: #cpp

In this blog, I will introduce how we can make vim work with a CMake Project.

Background

I was playing with cpp snippets today. I need to swap two integers. In python, we will do

a = 1
b = 2

a, b = b, a

In cpp, we usually introduce an temporary variable and swap these two integers.

void swap(int& a, int &b) {
    auto c = a;
    a = b;
    b = c;
}

Actually there is already std::swap in the standard library.

std::swap(a, b)

I am interested at which one has a higher performance.

Hands on

I am aware of the packages of benchmark. I need to use it to run some benchmark tests. From the Github page, it tells me how to build it from source. You can also install it using homebrew if you are on Mac.

brew install google-benchmark

I prefer not to pollute my own environment. I’d like to use CMake to manage everything.

cmake is installed using pip.

pip install cmake
cmake --version
# cmake version 3.31.2

Benchmark related code: “benchmark_example.cpp”

#include <utility>
#include <benchmark/benchmark.h>

static void BM_swap_with_temp(benchmark::State& state) {
    int a = 0, b = 1;
    for (auto _ : state) {
        auto c = a;
        a = b;
        b = c;
    }
}
// Register the function as a benchmark
BENCHMARK(BM_swap_with_temp);

// Define another benchmark
static void BM_swap_with_swap(benchmark::State& state) {
    int a = 0, b = 1;
    for (auto _ : state) {
        std::swap(a, b);
    }
}
BENCHMARK(BM_swap_with_swap);

BENCHMARK_MAIN();

It is very simple, just benchmark the two functions I am interested at.

cmake_minimum_required(VERSION 3.10)
project(BenchmarkExample)

# By default, it will compile a debug version
set(CMAKE_BUILD_TYPE Release)

# It is used to generate the compile_commands.json
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

# Set C++ standard to C++11 or later
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Enable FetchContent module
include(FetchContent)

# Download Google Benchmark if it's not installed
FetchContent_Declare(
    benchmark
    GIT_REPOSITORY https://github.com/google/benchmark.git
    GIT_TAG main  # This will get the latest version
)
# Fetch GoogleTest explicitly if needed
FetchContent_Declare(
    gtest
    GIT_REPOSITORY https://github.com/google/googletest.git
    GIT_TAG main  # Or specify a stable tag
)

FetchContent_MakeAvailable(gtest benchmark)

# Add the executable
add_executable(benchmark_example benchmark_example.cpp)

target_compile_definitions(benchmark_example PRIVATE BENCHMARK_DISABLE_CLOCK BENCHMARK_DISABLE_THREAD_AFFINITY)

# Link Google Benchmark
target_link_libraries(benchmark_example benchmark::benchmark)

so you can

mkdir -p build
cd build && cmake .. && make
./benchmark_example

Notes

  • It seems we cannot only fetch Google benchmark. It depends on googletest
  • We need to build a release in order to get more accurate results. You can also set in command line.
cmake -DCMAKE_BUILD_TYPE=Release
  • It is 2024. You still have to manually enable the C++11 to avoid warnings.

Results

  • If we don’t enable the Release build type, we can see the performance of std::swap is higher.
  • If we build a release version, I don’t see any performance difference.

Reference