From cppreference.com
classmonotonic_buffer_resource:publicstd::pmr::memory_resource;(since C++17)The class std::pmr::monotonic_buffer_resource is a special-purpose memory resource class that releases the allocated memory only when the resource is destroyed. It is 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.
monotonic_buffer_resource can be constructed with an initial buffer. If there is no initial buffer, or if the buffer is exhausted, additional buffers are obtained from an upstream memory resource supplied at construction. The size of buffers obtained follows a geometric progression.
monotonic_buffer_resource is not thread-safe.
Member functions
constructs a monotonic_buffer_resource
(public member function)
[virtual]
destroys a monotonic_buffer_resource, releasing all allocated memory
(virtual public member function)
operator=
[deleted]
copy assignment operator is deleted. monotonic_buffer_resource is not copy assignable
(public member function)
Public member functions
release all allocated memory
(public member function)
returns a pointer to the upstream memory resource
(public member function)
Protected member functions
[virtual]
allocate memory
(virtual protected member function)
[virtual]
no-op
(virtual protected member function)
[virtual]
compare for equality with another
(virtual protected member function)
Example
The 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).
Run this code
#include<array>#include<chrono>#include<cstddef>#include<iomanip>#include<iostream>#include<list>#include<memory_resource>template<typenameFunc>autobenchmark(Functest_func,intiterations){constautostart=std::chrono::system_clock::now();while(iterations-->0)test_func();constautostop=std::chrono::system_clock::now();constautosecs=std::chrono::duration<double>(stop-start);returnsecs.count();}intmain(){constexprintiterations{100};constexprinttotal_nodes{2'00'000};autodefault_std_alloc=[total_nodes]{std::list<int>list;for(inti{};i!=total_nodes;++i)list.push_back(i);};autodefault_pmr_alloc=[total_nodes]{std::pmr::list<int>list;for(inti{};i!=total_nodes;++i)list.push_back(i);};autopmr_alloc_no_buf=[total_nodes]{std::pmr::monotonic_buffer_resourcembr;std::pmr::polymorphic_allocator<int>pa{&mbr};std::pmr::list<int>list{pa};for(inti{};i!=total_nodes;++i)list.push_back(i);};autopmr_alloc_and_buf=[total_nodes]{std::array<std::byte,total_nodes*32>buffer;// enough to fit in all nodesstd::pmr::monotonic_buffer_resourcembr{buffer.data(),buffer.size()};std::pmr::polymorphic_allocator<int>pa{&mbr};std::pmr::list<int>list{pa};for(inti{};i!=total_nodes;++i)list.push_back(i);};constdoublet1=benchmark(default_std_alloc,iterations);constdoublet2=benchmark(default_pmr_alloc,iterations);constdoublet3=benchmark(pmr_alloc_no_buf,iterations);constdoublet4=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:
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