Microbenchmarking in C++ has long meant choosing between heavyweight frameworks that pull in dependencies and fragile hand-rolled timing code that produces unreliable results. ankerl::nanobench, a single-header library supporting C++11 through C++20, takes a different approach: measure everything, output everything, and keep the whole process under 60 milliseconds.
What nanobench measures
The library does not just report wall-clock time. Each benchmark run produces a table of metrics: nanoseconds per operation, operations per second, error percentage, instructions executed, CPU cycles, instructions per cycle, branch count, and branch prediction miss rate. These numbers come directly from hardware performance counters, not estimates or extrapolations, giving developers a precise picture of what the CPU is actually doing during a benchmarked function.
The example on the project's page shows a simple double-precision arithmetic loop completing in 7.52 nanoseconds per iteration, running roughly 133 million times per second with a 1.1% measurement error. The output also reveals that the code executes 6.65 instructions in 24.07 CPU cycles, yielding 0.276 instructions per cycle, and that a single branch in the loop misses prediction 8.9% of the time. That level of detail turns a benchmark from a black box into a diagnostic tool.
Single-header simplicity
Nanobench ships as a single header file. For small projects or quick experiments, you define ANKERL_NANOBENCH_IMPLEMENT in exactly one translation unit and include the header. Larger projects give the implementation its own file, avoiding duplicate symbol errors across multiple compilation units.
The API is minimal. You create a Bench object, call run with a name and a lambda containing the code you want to measure, and the library handles the rest. There is no boilerplate for setup or teardown, no configuration files, and no external dependencies beyond the C++ standard library and platform-specific performance counter access.
Compile times stay short because the header is self-contained and avoids heavy template metaprogramming. Integration into existing build systems is straightforward: drop the header into your include path and you are done.
Accuracy and robustness by design
The library's design goals center on three properties: speed, accuracy, and robustness. nanobench runs each benchmark multiple times automatically, collecting enough samples to report a meaningful error percentage. Outliers are detected and flagged, so developers know when a result is unreliable rather than silently averaging in noise.
The measurements are deterministic and repeatable. Running the same benchmark on the same hardware produces consistent results, which is essential for comparing micro-optimizations where differences of fractions of a nanosecond matter. The library warns when results do not meet its reliability thresholds, pushing developers to investigate rather than trust a misleading number.
For developers working on performance-critical code, whether in game engines,高频交易 systems, or low-latency networking, having a benchmarking tool that reports instruction counts and branch miss rates alongside timing data changes how you approach optimization. You can see whether a change improved IPC, reduced branch misses, or simply shifted work around without meaningfully changing throughput.
Where it fits in the C++ benchmarking ecosystem
Google Benchmark is the most widely used C++ microbenchmarking framework, but it pulls in more infrastructure and produces less detailed hardware-level output by default. follybench and other alternatives exist, but nanobench's single-header design and built-in performance counter integration give it a distinct niche: fast to adopt, fast to run, and fast to understand.
The library is available on GitHub under the MIT license, with releases tagged for stable versions. For developers who need quick, reliable, hardware-informed benchmarks without the overhead of a larger framework, nanobench covers the ground well.