1. Problem It Solves
A fixed PMR arena can remove heap allocation from a measured hot loop, while benchmarking measures a question and profiling locates system-wide cost. It makes an important assumption visible and checkable.
2. Prerequisites
PMR resources, containers, cache behavior, and chrono timing.
You should be able to compile a short program and read its output.
3. Core Idea
Prepare the workshop before timing: reserve storage from the arena, then measure only repeated work. A benchmark is a stopwatch; a profiler is a map. Read std::pmr::monotonic_buffer_resource as a precise promise; runtime preconditions still belong to the programmer.
4. Minimal Syntax
std::pmr::monotonic_buffer_resource arena{buffer.data(), buffer.size(), std::pmr::null_memory_resource()};5. How It Works
The program introduces the smallest relevant form of
std::pmr::monotonic_buffer_resource.It applies the feature to fixed data while required owners remain in scope.
It prints one result that can be checked against the source.
6. Common Mistakes
A tiny timing can be optimized away, dominated by noise, or answer the wrong question; a null upstream resource throws if the fixed buffer is exhausted.
Also check the required header, C++20 library support, lifetime, and deduced types.
7. When to Use It
Use it when allocation behavior is measured as a bottleneck and a bounded arena fits the lifetime.
Avoid it when ordinary allocation is not hot or object lifetimes must outgrow the arena.
8. Simple Example
A PMR vector reserves from a stack buffer before timing, then updates elements in a hot path without further allocation. The companion .cpp uses no input, so its result is easy to reproduce.
Complete sample code
Source file
cpp20/51_pmr_hot_path_benchmarking_profiling/main.cpp
// Day 51: PMR, Allocation-Free Hot Paths, Benchmarking, and Profiling
#include <array>
#include <chrono>
#include <cstddef>
#include <iostream>
#include <memory_resource>
#include <numeric>
#include <vector>
int main() {
std::array<std::byte, 4096> buffer{};
std::pmr::monotonic_buffer_resource arena{
buffer.data(), buffer.size(), std::pmr::null_memory_resource()};
std::pmr::vector<int> values{&arena};
values.reserve(100); // Allocate before the measured hot path.
for (int i = 0; i < 100; ++i) values.push_back(i);
auto start = std::chrono::steady_clock::now();
for (int repeat = 0; repeat < 1000; ++repeat) {
for (int& value : values) ++value;
}
auto elapsed = std::chrono::steady_clock::now() - start;
std::cout << "sum = " << std::accumulate(values.begin(), values.end(), 0) << '\n';
std::cout << "elapsed ns >= 0: " << std::boolalpha
<< (std::chrono::duration_cast<std::chrono::nanoseconds>(elapsed).count() >= 0)
<< '\n';
}
9. Key Takeaways
std::pmr::monotonic_buffer_resourceexpresses the central C++20 idea of this day.The example isolates one behavior with fixed data.
Compiler checks do not replace lifetime and runtime reasoning.
Prefer the smallest interface that states the real requirement.
10. Self-Check Questions
Easy — What is the main job of
std::pmr::monotonic_buffer_resourcein the minimal example?Medium — Why is
reserveperformed before the start timestamp?Hard — How does using
null_memory_resource()make an accidental buffer overflow visible instead of silently falling back to the heap?