Skip to content

Instantly share code, notes, and snippets.

@itzmeanjan
Last active February 21, 2024 22:18
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save itzmeanjan/05dc3e946f635d00c5e0b21aae6203a7 to your computer and use it in GitHub Desktop.
Save itzmeanjan/05dc3e946f635d00c5e0b21aae6203a7 to your computer and use it in GitHub Desktop.
Using Performance Monitoring Unit(s), when benchmarking with google-benchmark.

Background

I'm demonstrating following on a machine, running Ubuntu 22.04 with GNU/Linux kernel 5.19.0.

$ lsb_release -a
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 22.04.2 LTS
Release:	22.04
Codename:	jammy

$ uname -a
Linux bench-arm64 5.19.0-1028-aws #29~22.04.1-Ubuntu SMP Tue Jun 20 19:13:00 UTC 2023 aarch64 aarch64 aarch64 GNU/Linux

Prerequisites

  1. You must have installed build-essential, make, cmake and git.
sudo apt-get install build-essential make cmake git
  1. You must also install libpfm4-dev, following guide https://github.com/google/benchmark/blob/4931aefb/docs/perf_counters.md, so that google-benchmark can read performance counters such as CYCLES, INSTRUCTIONS etc. for each of registered benchmark functions.
sudo apt-get install libpfm4-dev

Building google-benchmark

  1. Clone google-benchmark repository.
git clone https://github.com/google/benchmark.git
git checkout v1.8.2 # latest release at time of writing this guide.
  1. Following installation guide from https://github.com/google/benchmark/#installation.
cmake -E make_directory "build"
cmake -E chdir "build" cmake -DBENCHMARK_ENABLE_GTEST_TESTS=OFF -DBENCHMARK_ENABLE_LIBPFM=on -DCMAKE_BUILD_TYPE=Release ../

# Perform system-wide installation of header and built library
sudo cmake --build "build" --config Release --target install -j
  1. Ensure that libpfm4 can collect CPU cycle count, retired instructions etc. using performance monitoring unit (PMU).
# Thanks to https://superuser.com/a/1404110
sudo sh -c 'echo kernel.perf_event_paranoid=-1 >> /etc/sysctl.conf'

# You can always go further and do a system restart, though following
# should suffice for running session.
sudo sysctl -p

Using google-benchmark

  1. Write following C++ example program.
// main.cpp, taken from https://github.com/google/benchmark/#basic-usage
#include <benchmark/benchmark.h>

static void
BM_StringCreation(benchmark::State& state)
{
  for (auto _ : state)
    std::string empty_string;
}
// Register the function as a benchmark
BENCHMARK(BM_StringCreation);

// Define another benchmark
static void
BM_StringCopy(benchmark::State& state)
{
  std::string x = "hello";
  for (auto _ : state)
    std::string copy(x);
}
BENCHMARK(BM_StringCopy);

BENCHMARK_MAIN();
  1. Compile it, by issuing following command.
g++ -std=c++11 -Wall -O3 -march=native main.cpp -lbenchmark -lpthread -lpfm
  1. Run it with following command.
./a.out  --benchmark_perf_counters=CYCLES,INSTRUCTIONS --benchmark_counters_tabular=true

Screenshot from 2023-07-07 20-04-03

  1. You must disable CPU frequency scaling during benchmarking, follow this guide.
  2. Get to know more about google-benchmark @ https://github.com/google/benchmark/tree/4931aefb/docs.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment