Library / SDK
google/benchmark avatar
google/benchmark

Google Benchmark: measuring C++ code the way a test suite measures correctness

A microbenchmark support library

10,463 stars1,808 forksC++Apache-2.0

At a glance

What is it?
The microbenchmark library from the Google Test family, built around a State loop that decides iteration count for you, with a cmake build, Python bindings and a strict split between the stable main branch and an experimental v2 branch.
Who is it for?
Google Benchmark is the right default for C++ and for the Python bindings it ships, because the State loop removes the two mistakes that produce most bad microbenchmarks, a hardcoded iteration count and code that the optimizer can throw away. The case against it is a codebase that measures whole applications rather than snippets, where a per-process timing harness tells you more than repeated in-process loops.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly C++, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 11, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The State loop is the whole API in miniature

The example at the top of the README is a complete benchmark, registration and main included:

c++
#include <benchmark/registration.h>
#include <benchmark/state.h>

static void BM_SomeFunction(benchmark::State& state) {
  // Perform setup here
  for (auto _ : state) {
    // This code gets timed
    SomeFunction();
  }
}
// Register the function as a benchmark
BENCHMARK(BM_SomeFunction);
// Run the benchmark
BENCHMARK_MAIN();

The range-based for over state is the part worth understanding. The library decides how many iterations to run, growing the count until the measurement passes a time threshold, and the loop body runs once per iteration. Your job is to put only the timed work inside it, with setup before the loop, exactly as the comment suggests.

The alternative spelling shown later in the README declares the function against benchmark::State by reference and registers with the same BENCHMARK macro, so a second benchmark such as a string copy is a few lines rather than a new mechanism. The README also points at the Google Test documentation, and the reason is structural: this library deliberately mirrors the shape of a test framework, with registration macros and a main, so if you already use one of them the other needs no explanation.

Building with cmake and what lands in the build directory

The installation section assumes git and cmake are already present. The sequence configures with dependency download turned on, which matters because Google Test is needed for the test suite:

bash
$ git clone https://github.com/google/benchmark.git
$ cd benchmark
$ cmake -E make_directory "build"
$ cmake -DBENCHMARK_DOWNLOAD_DEPENDENCIES=on -DCMAKE_BUILD_TYPE=Release -S . -B "build"
$ cmake --build "build" --config Release

That produces the two libraries you actually link against, benchmark and benchmark_main, plus tests, laid out like this on a unix system:

code
/benchmark
  /build
    /src
      /libbenchmark.a
      /libbenchmark_main.a
    /test

Google Test can arrive two ways, and the README is explicit about both. Either check its sources out into benchmark/googletest yourself, or let the -DBENCHMARK_DOWNLOAD_DEPENDENCIES=ON flag fetch and build it during configuration. If you would rather not build tests at all, add -DBENCHMARK_ENABLE_GTEST_TESTS=OFF to CMAKE_ARGS.

Linking your own file afterwards is a single compiler invocation, and the flag that answers the requirements section in one line is the standard here:

bash
$ g++ mybenchmark.cc -std=c++11 -isystem benchmark/include \
  -Lbenchmark/build/src -lbenchmark -lpthread -o mybenchmark

That -std=c++11 is not a contradiction of the requirements text. The README says the library can be used with C++11 while requiring C++17 to build it, so your code compiles at the older standard and the library itself is built with a newer toolchain.

The flags that decide whether your numbers mean anything

By default the library builds as a debug build, and the README says you will see a warning in the output when that is the case. Add -DCMAKE_BUILD_TYPE=Release when generating the build system to avoid measuring unoptimized code. The --config Release you pass to the build command is a separate concern: it is needed for multi-configuration generators such as Visual Studio and can be skipped for Makefile-style builds.

Two further options change the measurement rather than the ergonomics. -DBENCHMARK_ENABLE_LTO=true turns on link-time optimization, which matters for small functions that otherwise pay a call through the library boundary. And the README names the cache variables that need setting when autodetection fails: GCC_AR and GCC_RANLIB for gcc, and LLVMAR_EXECUTABLE, LLVMNM_EXECUTABLE and LLVMRANLIB_EXECUTABLE for clang.

Sanitizer builds are supported through compiler and standard library flags rather than a project option:

code
 -DCMAKE_C_FLAGS="-g -O2 -fno-omit-frame-pointer -fsanitize=address -fsanitize=thread -fno-sanitize-recover=all"

There is one more piece of environment control that only shows up in the release history, and it is worth knowing about because it explains surprising numbers. Work in the 1.9.3 release added ASLR status detection and reporting, plus automatic ASLR disablement, and the 1.9.4 release fixed the re-entry path both outside and inside Docker. Address space layout randomization moves code addresses between runs, which adds variance to memory-sensitive measurements, and this library now handles that for you and tells you when it did.

Main is stable, the v2 branch is a promise of nothing

The stability policy is short and unusually clear. The main branch holds the latest stable version, its API can be considered largely stable, and source breaking changes happen only when a new major version is released. Experimental features live on a separate v2 branch, are implemented and tested there, and come with an explicit warning that there are no stability guarantees and the API may change or break at any time.

That split matters more here than in most libraries, because a benchmarking library's output gets compared across runs, and a change in how the framework measures invalidates the comparison. Pinning to a major version is the mechanism the policy relies on.

The release cadence supports that reading. Three releases are on record: 1.9.3 and 1.9.4 in May 2025, then 1.9.5 in January 2026. The 1.9.5 list is dominated by packaging and platform edges, a range check in the Python binding, a fix for editable installs of the Python package, deprecation warnings for MSVC, a Windows link fix for Shlwapi, better handling of private link libraries in pkg-config generation, and a guard so the Intel compiler flag is only applied when that compiler is actually in use. Version 1.9.4 enabled running in WebAssembly with the filesystem disabled and moved Linux ARM wheel builds onto native ARM runners.

Python bindings, WebAssembly and the files around the library

The bindings are a first-class part of the repository rather than an afterthought. The tree carries a bindings directory, and pyproject.toml describes a distribution named google_benchmark that requires Python 3.10 or newer, maps its package directory to bindings/python, and reads its version dynamically from the google_benchmark package attribute. Classifiers list Python 3.10 through 3.13, and the development status is recorded as Beta.

setup.py shows what publishing that distribution actually involves: it detects Windows, macOS and Linux, applies the stable ABI options when running on Python 3.12 or newer so wheels are not tied to a minor version, and patches the rules_python toolchain definition when building under cibuildwheel inside a Linux container so the toolchain tolerates running as root. That is a fair amount of machinery for a binding, and it explains the several packaging fixes in the recent release notes.

The repository also carries build files for both ecosystems, CMakeLists.txt at the root alongside BUILD.bazel, MODULE.bazel, WORKSPACE and WORKSPACE.bzlmod, with a bazel directory and a .bazelversion. A pyproject.toml with ruff and mypy configuration, a .clang-format and a .clang-tidy sit alongside .pre-commit-config.yaml and an AGENTS.md, so the linting story is broad rather than incidental.

The README points at seven docs files for everything else

Once you have built the library, the README is mostly a table of contents. It links docs/user_guide.md as the comprehensive feature overview, docs/tools.md for additional tooling, docs/AssemblyTests.md for assembly-level testing, docs/python_bindings.md for building and installing the Python bindings, docs/dependencies.md for supported compilers and standards, and docs/platform_specific_build_instructions.md for the platforms that need special handling.

Two of those are worth prioritizing for most readers. The user guide is where the features that shape a benchmark file are described, including counters, repetitions and the reporting controls, and the dependencies page is the one to consult before filing a compiler support request, since the README says patches for a particular compiler are welcome, which implies a list of what already works. The platform-specific instructions matter on Windows and on toolchains where the default search paths do not match.

For asking questions there is a Google group for benchmark discussion, a Discord server linked from the badges at the top, and an IRC channel on libera. The repository's last push was on 2026-09-21 and it is not archived, under the Apache License 2.0, which is the usual arrangement for a library this widely embedded in other people's builds.

Editorial conclusion

Google Benchmark is the right default for C++ and for the Python bindings it ships, because the State loop removes the two mistakes that produce most bad microbenchmarks, a hardcoded iteration count and code that the optimizer can throw away. The case against it is a codebase that measures whole applications rather than snippets, where a per-process timing harness tells you more than repeated in-process loops. Verify two things before trusting a number it prints: that you built with a release configuration rather than the debug default, and whether the operation you timed can be hoisted out of the loop, since the library detects dead code elimination and reports it. The user guide in docs/user_guide.md is where the reporting, repetitions and custom counters options are documented, and it is worth more of your time than the README.

Frequently asked questions

How do I install Google Benchmark on Linux?

Clone the repository, make a build directory, and configure with cmake using -DBENCHMARK_DOWNLOAD_DEPENDENCIES=on so Google Test is fetched and built for the test suite, then build with cmake --build and the Release config. The result is libbenchmark.a and libbenchmark_main.a under the build src directory.

What does the benchmark::State loop do in a benchmark function?

The range-based for over benchmark::State is the timing loop, and the library chooses the iteration count so the run lasts long enough to be measurable. Setup belongs before the loop and only the code under test belongs inside it, which is what the README's example comments indicate.

Do I need Google Test to build Google Benchmark?

Google Benchmark needs Google Test to build and run its own tests. You can either check the Google Test sources out into benchmark/googletest, or let the cmake flag -DBENCHMARK_DOWNLOAD_DEPENDENCIES=ON download and build it during configuration, or skip the tests entirely with -DBENCHMARK_ENABLE_GTEST_TESTS=OFF.

Which branch should I use, main or v2?

Main carries the latest stable release, with source breaking changes only at a new major version. The v2 branch holds newer experimental features and explicitly offers no stability guarantees, so it is for testing and feedback rather than for pinning a build.

Official sources

  1. google/benchmark on GitHub
  2. Issues
  3. License: Apache-2.0
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/google-benchmark.svg)](https://hysenlabs.com/projects/google-benchmark)