std::pmr::m...fer_resource(3)
π NAME π
std::pmr::monotonic_buffer_resource β bestie, the name is literally just std::pmr::monotonic_buffer_resource again. No cute nickname, no extra lore. We move. π
(also hii, real quick β this is a page from the C++ Standard Libary man pages, section (3), and the title up top got cut off as std::pmr::m...fer_resource(3) because apparently even the manpage had a whole moment there π)
β¨ SYNOPSIS β¨
Defined in header <memory_resource>:
class monotonic_buffer_resource : public std::pmr::memory_resource;
(since C++17) π
π¦ DESCRIPTION π¦
okay so picture this: std::pmr::monotonic_buffer_resource is this special-purpose memory resource class, right? And the whole vibe is that it only releases the allocated memory when the resource is destroyed. That's it. That's the personality. It hoards everything until the very end and then drops it all at once. Main character energy fr. π
It's intended for very fast memory allocations in situations where memory is used to build up a few objects and then is released all at once. Build things up, yeet them all together β iconic behavior, no notes.
Here's the tea on how it works π β monotonic_buffer_resource can be constructed with an initial buffer. But if there's no initial buffer, or if the buffer gets exhausted (rip, it ran out), then additional buffers are obtained from an upstream memory resource supplied at construction. And the size of the buffers it obtains follows a geometric progression. It's giving "growth mindset." π±
β οΈ Warning bestie: monotonic_buffer_resource is not thread-safe. Do not share it across threads unless you're ready for chaos. This is not a group project resource. π
πΈ MEMBER FUNCTIONS πΈ
constructorβ constructs amonotonic_buffer_resource(public member function)destructor[virtual]β destroys amonotonic_buffer_resource, releasing all allocated memory (virtual public member function)operator=[deleted]β copy assignment operator is deleted.monotonic_buffer_resourceis not copy assignable (public member function)
π PUBLIC MEMBER FUNCTIONS π
releaseβ release all allocated memory (public member function)upstream_resourceβ returns a pointer to the upstream memory resource (public member function)
π PROTECTED MEMBER FUNCTIONS π
do_allocate[virtual]β allocate memory (virtual protected member function)do_deallocate[virtual]β no-op (virtual protected member function)do_is_equal[virtual]β compare for equality with anotherstd::pmr::memory_resource(virtual protected member function)
π₯ EXAMPLE π₯
This program measures the time of creating huge double-linked lists using the following allocators πβ¨:
- default standard allocator,
- default pmr allocator,
- pmr allocator with monotonic resource but without explicit memory buffer,
- pmr allocator with monotonic resource and external memory buffer (on stack).
(There's a // Run this code link hanging out at the top of the box on the original page, btw β that's where you'd click to actually send it. π«Ά)
#include <array>
#include <chrono>
#include <cstddef>
#include <iomanip>
#include <iostream>
#include <list>
#include <memory_resource>
template<typename Func>
auto benchmark(Func test_func, int iterations)
{
const auto start = std::chrono::system_clock::now();
while (iterations-- > 0)
test_func();
const auto stop = std::chrono::system_clock::now();
const auto secs = std::chrono::duration<double>(stop - start);
return secs.count();
}
int main()
{
constexpr int iterations{100};
constexpr int total_nodes{2'00'000};
auto default_std_alloc = [total_nodes]
{
std::list<int> list;
for (int i{}; i != total_nodes; ++i)
list.push_back(i);
};
auto default_pmr_alloc = [total_nodes]
{
std::pmr::list<int> list;
for (int i{}; i != total_nodes; ++i)
list.push_back(i);
};
auto pmr_alloc_no_buf = [total_nodes]
{
std::pmr::monotonic_buffer_resource mbr;
std::pmr::polymorphic_allocator<int> pa{&mbr};
std::pmr::list<int> list{pa};
for (int i{}; i != total_nodes; ++i)
list.push_back(i);
};
auto pmr_alloc_and_buf = [total_nodes]
{
std::array<std::byte, total_nodes * 32> buffer; // enough to fit in all nodes
std::pmr::monotonic_buffer_resource mbr{buffer.data(), buffer.size()};
std::pmr::polymorphic_allocator<int> pa{&mbr};
std::pmr::list<int> list{pa};
for (int i{}; i != total_nodes; ++i)
list.push_back(i);
};
const double t1 = benchmark(default_std_alloc, iterations);
const double t2 = benchmark(default_pmr_alloc, iterations);
const double t3 = benchmark(pmr_alloc_no_buf , iterations);
const double t4 = benchmark(pmr_alloc_and_buf, iterations);
std::cout << std::fixed << std::setprecision(3)
<< "t1 (default std alloc): " << t1 << " sec; t1/t1: " << t1/t1 << '\n'
<< "t2 (default pmr alloc): " << t2 << " sec; t1/t2: " << t1/t2 << '\n'
<< "t3 (pmr alloc no buf): " << t3 << " sec; t1/t3: " << t1/t3 << '\n'
<< "t4 (pmr alloc and buf): " << t4 << " sec; t1/t4: " << t1/t4 << '\n';
}
β POSSIBLE OUTPUT β
like, possible, bestie β your numbers may vary, don't come for me π
t1 (default std alloc): 0.720 sec; t1/t1: 1.000
t2 (default pmr alloc): 0.915 sec; t1/t2: 0.787
t3 (pmr alloc no buf): 0.370 sec; t1/t3: 1.945
t4 (pmr alloc and buf): 0.247 sec; t1/t4: 2.914
and that's the whole page, bestie π«Άβ¨ this lil' rewrite comes to you from http://cppreference.com, dated 2024.06.10, and the original footer line was std::pmr::m...fer_resource(3) β same truncation, same energy. go forth and allocate monotonically, ilysm π
π¦ where this page comes from
- nixpkgs unstable: stdman 2024.07.05
- opensuse-leap 16.0: stdman 2024.07.05-bp160.1.9 Β· MIT
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms