{"id":8337,"date":"2023-10-09T17:09:22","date_gmt":"2023-10-09T17:09:22","guid":{"rendered":"https:\/\/www.modernescpp.com\/?p=8337"},"modified":"2023-10-09T17:09:22","modified_gmt":"2023-10-09T17:09:22","slug":"optimization-with-allocators-in-c17","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/optimization-with-allocators-in-c17\/","title":{"rendered":"Optimization with Allocators in C++17"},"content":{"rendered":"\n<p>Thanks to polymorphic allocators in C++17, you can optimize your memory allocation. This optimization includes performance and the reuse of memory.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large is-resized\"><img decoding=\"async\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/memory-8141642_1280-1030x686.jpg\" alt=\"\" class=\"wp-image-8339\" style=\"width:500px\" width=\"500\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/memory-8141642_1280-1030x686.jpg 1030w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/memory-8141642_1280-300x200.jpg 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/memory-8141642_1280-768x512.jpg 768w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/memory-8141642_1280-705x470.jpg 705w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/memory-8141642_1280.jpg 1280w\" sizes=\"(max-width: 1030px) 100vw, 1030px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Performance<\/h2>\n\n\n\n<p>The following program is from <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/memory\/monotonic_buffer_resource\" data-type=\"link\" data-id=\"https:\/\/en.cppreference.com\/w\/cpp\/memory\/monotonic_buffer_resource\">cppreference.com\/monotonic_buffer_resource<\/a>. I will explain and extend its performance test to Clang and the MSVC compiler.<\/p>\n\n\n\n<!-- HTML generated using hilite.me --><div style=\"background: #f0f3f3; overflow:auto;width:auto; gray;border-width:.1em .1em .1em .8em\"><pre style=\"margin: 0; line-height: 125%\"><span style=\"color: #0099FF; font-style: italic\">\/\/ pmrPerformance.cpp<\/span>\n<span style=\"color: #0099FF; font-style: italic\">\/\/ https:\/\/en.cppreference.com\/w\/cpp\/memory\/monotonic_buffer_resource<\/span>\n\n<span style=\"color: #009999\">#include &lt;array&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;chrono&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;cstddef&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;iomanip&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;iostream&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;list&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;memory_resource&gt;<\/span>\n \n<span style=\"color: #006699; font-weight: bold\">template<\/span><span style=\"color: #555555\">&lt;<\/span><span style=\"color: #006699; font-weight: bold\">typename<\/span> Func<span style=\"color: #555555\">&gt;<\/span>\n<span style=\"color: #006699; font-weight: bold\">auto<\/span> benchmark(Func test_func, <span style=\"color: #007788; font-weight: bold\">int<\/span> iterations)              <span style=\"color: #0099FF; font-style: italic\">\/\/ (1)<\/span>\n{\n    <span style=\"color: #006699; font-weight: bold\">const<\/span> <span style=\"color: #006699; font-weight: bold\">auto<\/span> start <span style=\"color: #555555\">=<\/span> std<span style=\"color: #555555\">::<\/span>chrono<span style=\"color: #555555\">::<\/span>system_clock<span style=\"color: #555555\">::<\/span>now();\n    <span style=\"color: #006699; font-weight: bold\">while<\/span> (iterations<span style=\"color: #555555\">--<\/span> <span style=\"color: #555555\">&gt;<\/span> <span style=\"color: #FF6600\">0<\/span>)\n        test_func();\n    <span style=\"color: #006699; font-weight: bold\">const<\/span> <span style=\"color: #006699; font-weight: bold\">auto<\/span> stop <span style=\"color: #555555\">=<\/span> std<span style=\"color: #555555\">::<\/span>chrono<span style=\"color: #555555\">::<\/span>system_clock<span style=\"color: #555555\">::<\/span>now();\n    <span style=\"color: #006699; font-weight: bold\">const<\/span> <span style=\"color: #006699; font-weight: bold\">auto<\/span> secs <span style=\"color: #555555\">=<\/span> std<span style=\"color: #555555\">::<\/span>chrono<span style=\"color: #555555\">::<\/span>duration<span style=\"color: #555555\">&lt;<\/span><span style=\"color: #007788; font-weight: bold\">double<\/span><span style=\"color: #555555\">&gt;<\/span>(stop <span style=\"color: #555555\">-<\/span> start);\n    <span style=\"color: #006699; font-weight: bold\">return<\/span> secs.count();\n}\n \n<span style=\"color: #007788; font-weight: bold\">int<\/span> main()\n{\n    constexpr <span style=\"color: #007788; font-weight: bold\">int<\/span> iterations{<span style=\"color: #FF6600\">100<\/span>};\n    constexpr <span style=\"color: #007788; font-weight: bold\">int<\/span> total_nodes{<span style=\"color: #FF6600\">2<\/span><span style=\"color: #AA0000; background-color: #FFAAAA\">&#39;<\/span><span style=\"color: #FF6600\">00<\/span><span style=\"color: #AA0000; background-color: #FFAAAA\">&#39;<\/span><span style=\"color: #FF6600\">000<\/span>};\n \n    <span style=\"color: #006699; font-weight: bold\">auto<\/span> default_std_alloc <span style=\"color: #555555\">=<\/span> [total_nodes]            <span style=\"color: #0099FF; font-style: italic\">\/\/ (2)<\/span>\n    {\n        std<span style=\"color: #555555\">::<\/span>list<span style=\"color: #555555\">&lt;<\/span><span style=\"color: #007788; font-weight: bold\">int<\/span><span style=\"color: #555555\">&gt;<\/span> list;\n        <span style=\"color: #006699; font-weight: bold\">for<\/span> (<span style=\"color: #007788; font-weight: bold\">int<\/span> i{}; i <span style=\"color: #555555\">!=<\/span> total_nodes; <span style=\"color: #555555\">++<\/span>i)\n            list.push_back(i);\n    };\n \n    <span style=\"color: #006699; font-weight: bold\">auto<\/span> default_pmr_alloc <span style=\"color: #555555\">=<\/span> [total_nodes]            <span style=\"color: #0099FF; font-style: italic\">\/\/ (3)<\/span>\n    {\n        std<span style=\"color: #555555\">::<\/span>pmr<span style=\"color: #555555\">::<\/span>list<span style=\"color: #555555\">&lt;<\/span><span style=\"color: #007788; font-weight: bold\">int<\/span><span style=\"color: #555555\">&gt;<\/span> list;\n        <span style=\"color: #006699; font-weight: bold\">for<\/span> (<span style=\"color: #007788; font-weight: bold\">int<\/span> i{}; i <span style=\"color: #555555\">!=<\/span> total_nodes; <span style=\"color: #555555\">++<\/span>i)\n            list.push_back(i);\n    };\n \n    <span style=\"color: #006699; font-weight: bold\">auto<\/span> pmr_alloc_no_buf <span style=\"color: #555555\">=<\/span> [total_nodes]             <span style=\"color: #0099FF; font-style: italic\">\/\/ (4)<\/span>\n    {\n        std<span style=\"color: #555555\">::<\/span>pmr<span style=\"color: #555555\">::<\/span>monotonic_buffer_resource mbr;\n        std<span style=\"color: #555555\">::<\/span>pmr<span style=\"color: #555555\">::<\/span>polymorphic_allocator<span style=\"color: #555555\">&lt;<\/span><span style=\"color: #007788; font-weight: bold\">int<\/span><span style=\"color: #555555\">&gt;<\/span> pa{<span style=\"color: #555555\">&amp;<\/span>mbr};\n        std<span style=\"color: #555555\">::<\/span>pmr<span style=\"color: #555555\">::<\/span>list<span style=\"color: #555555\">&lt;<\/span><span style=\"color: #007788; font-weight: bold\">int<\/span><span style=\"color: #555555\">&gt;<\/span> list{pa};\n        <span style=\"color: #006699; font-weight: bold\">for<\/span> (<span style=\"color: #007788; font-weight: bold\">int<\/span> i{}; i <span style=\"color: #555555\">!=<\/span> total_nodes; <span style=\"color: #555555\">++<\/span>i)\n            list.push_back(i);\n    };\n \n    <span style=\"color: #006699; font-weight: bold\">auto<\/span> pmr_alloc_and_buf <span style=\"color: #555555\">=<\/span> [total_nodes]            <span style=\"color: #0099FF; font-style: italic\">\/\/ (5)<\/span>\n    {\n        std<span style=\"color: #555555\">::<\/span>array<span style=\"color: #555555\">&lt;<\/span>std<span style=\"color: #555555\">::<\/span>byte, total_nodes <span style=\"color: #555555\">*<\/span> <span style=\"color: #FF6600\">32<\/span><span style=\"color: #555555\">&gt;<\/span> buffer; <span style=\"color: #0099FF; font-style: italic\">\/\/ enough to fit in all nodes<\/span>\n        std<span style=\"color: #555555\">::<\/span>pmr<span style=\"color: #555555\">::<\/span>monotonic_buffer_resource mbr{buffer.data(), buffer.size()};\n        std<span style=\"color: #555555\">::<\/span>pmr<span style=\"color: #555555\">::<\/span>polymorphic_allocator<span style=\"color: #555555\">&lt;<\/span><span style=\"color: #007788; font-weight: bold\">int<\/span><span style=\"color: #555555\">&gt;<\/span> pa{<span style=\"color: #555555\">&amp;<\/span>mbr};\n        std<span style=\"color: #555555\">::<\/span>pmr<span style=\"color: #555555\">::<\/span>list<span style=\"color: #555555\">&lt;<\/span><span style=\"color: #007788; font-weight: bold\">int<\/span><span style=\"color: #555555\">&gt;<\/span> list{pa};\n        <span style=\"color: #006699; font-weight: bold\">for<\/span> (<span style=\"color: #007788; font-weight: bold\">int<\/span> i{}; i <span style=\"color: #555555\">!=<\/span> total_nodes; <span style=\"color: #555555\">++<\/span>i)\n            list.push_back(i);\n    };\n \n    <span style=\"color: #006699; font-weight: bold\">const<\/span> <span style=\"color: #007788; font-weight: bold\">double<\/span> t1 <span style=\"color: #555555\">=<\/span> benchmark(default_std_alloc, iterations);\n    <span style=\"color: #006699; font-weight: bold\">const<\/span> <span style=\"color: #007788; font-weight: bold\">double<\/span> t2 <span style=\"color: #555555\">=<\/span> benchmark(default_pmr_alloc, iterations);\n    <span style=\"color: #006699; font-weight: bold\">const<\/span> <span style=\"color: #007788; font-weight: bold\">double<\/span> t3 <span style=\"color: #555555\">=<\/span> benchmark(pmr_alloc_no_buf , iterations);\n    <span style=\"color: #006699; font-weight: bold\">const<\/span> <span style=\"color: #007788; font-weight: bold\">double<\/span> t4 <span style=\"color: #555555\">=<\/span> benchmark(pmr_alloc_and_buf, iterations);\n \n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> std<span style=\"color: #555555\">::<\/span>fixed <span style=\"color: #555555\">&lt;&lt;<\/span> std<span style=\"color: #555555\">::<\/span>setprecision(<span style=\"color: #FF6600\">3<\/span>)\n              <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;t1 (default std alloc): &quot;<\/span> <span style=\"color: #555555\">&lt;&lt;<\/span> t1 <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot; sec; t1\/t1: &quot;<\/span> <span style=\"color: #555555\">&lt;&lt;<\/span> t1<span style=\"color: #555555\">\/<\/span>t1 <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>\n              <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;t2 (default pmr alloc): &quot;<\/span> <span style=\"color: #555555\">&lt;&lt;<\/span> t2 <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot; sec; t1\/t2: &quot;<\/span> <span style=\"color: #555555\">&lt;&lt;<\/span> t1<span style=\"color: #555555\">\/<\/span>t2 <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>\n              <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;t3 (pmr alloc  no buf): &quot;<\/span> <span style=\"color: #555555\">&lt;&lt;<\/span> t3 <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot; sec; t1\/t3: &quot;<\/span> <span style=\"color: #555555\">&lt;&lt;<\/span> t1<span style=\"color: #555555\">\/<\/span>t3 <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>\n              <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;t4 (pmr alloc and buf): &quot;<\/span> <span style=\"color: #555555\">&lt;&lt;<\/span> t4 <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot; sec; t1\/t4: &quot;<\/span> <span style=\"color: #555555\">&lt;&lt;<\/span> t1<span style=\"color: #555555\">\/<\/span>t4 <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n}\n<\/pre><\/div>\n\n\n\n<p>This performance test  in line (1) executes the functions in lines 2 &#8211; 5 one hundred times (<code>constexpr int iterations{100}<\/code>) . Each call of the functions creates a <code>std::pmr::list&lt;int&gt; <\/code>of two hundred thousand nodes (<code>constexpr int total_nodes{2'00'000<\/code>}). The nodes of each list are allocated in different ways:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Line 2: <code>std::list&lt;int&gt;<\/code> uses the global <code>operator new<\/code><\/li>\n\n\n\n<li>Line 3: <code>std::pmr::list&lt;int&gt;<\/code> uses the special memory resource<code> std::pmr::new_delete_resource<\/code><\/li>\n\n\n\n<li>Line 4: <code>std::pmr::list&lt;int&gt;<\/code> uses <code>std::pmr::monoton<\/code>ic_<code>buffer <\/code>without a preallocated buffer on the stack<\/li>\n\n\n\n<li>Line 5: <code>std::pmr::list<\/code> uses<code> std::pmr::monotonic_buffer <\/code>with a preallocated buffer on the stack<\/li>\n<\/ul>\n\n\n\n<p>The comment to the last function (line 5) states that the stack has enough space to fit all nodes: &#8220;<em>enough to fit in all nodes<\/em>&#8220;. This was correct on my Linux PC but not on my Windows PC. On Linux, the default for the stack size is 8 MB, but on Windows only 1 MB. Consequentially, my program execution on Windows using the MSVC compiler and the Clang compiler failed silently. I fixed it by changing with the help of <code>editbin.exe <\/code>the stack size of my MSVC and Clang executables:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large is-resized\"><img decoding=\"async\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/stacksizeWindows-1030x157.png\" alt=\"\" class=\"wp-image-8354\" style=\"width:500px\" width=\"500\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/stacksizeWindows-1030x157.png 1030w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/stacksizeWindows-300x46.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/stacksizeWindows-768x117.png 768w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/stacksizeWindows-705x107.png 705w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/stacksizeWindows.png 1425w\" sizes=\"(max-width: 1030px) 100vw, 1030px\" \/><\/figure>\n\n\n\n<p>Finally, here are the numbers. The reference value is the allocation with<code> std::list&lt;int&gt;<\/code> (line 2). Don&#8217;t compare the absolute numbers but the relative numbers because I used a virtualized Linux PC and a non-virtual Windows PC. Additionally, I enabled full optimization. This means (<code>\/Ox<\/code>) for the MSVC compiler and (<code>-Ox<\/code>) for the GCC and Clang compilers.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Clang Compiler<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large is-resized\"><img decoding=\"async\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/pmrPerformanceClang-1030x301.png\" alt=\"\" class=\"wp-image-8359\" style=\"width:600px\" width=\"600\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/pmrPerformanceClang-1030x301.png 1030w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/pmrPerformanceClang-300x88.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/pmrPerformanceClang-768x224.png 768w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/pmrPerformanceClang-705x206.png 705w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/pmrPerformanceClang.png 1425w\" sizes=\"(max-width: 1030px) 100vw, 1030px\" \/><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li>GCC Compiler<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><img decoding=\"async\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/pmrPerformanceGCC.png\" alt=\"\" class=\"wp-image-8360\" style=\"width:600px\" width=\"600\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/pmrPerformanceGCC.png 567w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/pmrPerformanceGCC-300x126.png 300w\" sizes=\"(max-width: 567px) 100vw, 567px\" \/><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li>MSVC Compiler<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large is-resized\"><img decoding=\"async\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/pmrPerformanceCl.exe_-1030x309.png\" alt=\"\" class=\"wp-image-8361\" style=\"width:600px\" width=\"600\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/pmrPerformanceCl.exe_-1030x309.png 1030w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/pmrPerformanceCl.exe_-300x90.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/pmrPerformanceCl.exe_-768x231.png 768w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/pmrPerformanceCl.exe_-705x212.png 705w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/pmrPerformanceCl.exe_.png 1425w\" sizes=\"(max-width: 1030px) 100vw, 1030px\" \/><\/figure>\n\n\n\n<p>Interestingly, the memory resource<code> std::pmr::new_delete_resource<\/code> was always the slowest memory allocation. On the contrary, <code>std::pmr::monotonic_buffer<\/code> the fastest memory allocation. This holds particularly if you use a preallocated buffer on the stack. On Windows, memory allocation is about 10 times faster.<\/p>\n\n\n\n<p>There is another optimization potential of <code>std::pmr::new_delete_resource<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Memory Reuse<\/h2>\n\n\n\n<p><code>std::pmr::monotonic_buffer<\/code> enables the reuse of memory, and you can, therefor, spare the to free the memory. <\/p>\n\n\n\n<!-- HTML generated using hilite.me --><div style=\"background: #f0f3f3; overflow:auto;width:auto; gray;border-width:.1em .1em .1em .8em\"><pre style=\"margin: 0; line-height: 125%\"><span style=\"color: #0099FF; font-style: italic\">\/\/ reuseMemory.cpp<\/span>\n\n<span style=\"color: #009999\">#include &lt;array&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;cstddef&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;iostream&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;memory_resource&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;string&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;vector&gt;<\/span>\n\n<span style=\"color: #007788; font-weight: bold\">int<\/span> <span style=\"color: #CC00FF\">main<\/span>() {\n \n    std<span style=\"color: #555555\">::<\/span>array<span style=\"color: #555555\">&lt;<\/span>std<span style=\"color: #555555\">::<\/span>byte, <span style=\"color: #FF6600\">2000<\/span><span style=\"color: #555555\">&gt;<\/span> buf;\n\n    <span style=\"color: #006699; font-weight: bold\">for<\/span> (<span style=\"color: #007788; font-weight: bold\">int<\/span> i <span style=\"color: #555555\">=<\/span> <span style=\"color: #FF6600\">0<\/span>; i <span style=\"color: #555555\">&lt;<\/span> <span style=\"color: #FF6600\">100<\/span>; <span style=\"color: #555555\">++<\/span>i) {                                       <span style=\"color: #0099FF; font-style: italic\">\/\/ (1)<\/span>\n        std<span style=\"color: #555555\">::<\/span>pmr<span style=\"color: #555555\">::<\/span>monotonic_buffer_resource pool{buf.data(), buf.size(),  <span style=\"color: #0099FF; font-style: italic\">\/\/ (2)<\/span>\n                                                std<span style=\"color: #555555\">::<\/span>pmr<span style=\"color: #555555\">::<\/span>null_memory_resource()};\n        std<span style=\"color: #555555\">::<\/span>pmr<span style=\"color: #555555\">::<\/span>vector<span style=\"color: #555555\">&lt;<\/span>std<span style=\"color: #555555\">::<\/span>pmr<span style=\"color: #555555\">::<\/span>string<span style=\"color: #555555\">&gt;<\/span> myVec{<span style=\"color: #555555\">&amp;<\/span>pool};\n        <span style=\"color: #006699; font-weight: bold\">for<\/span> (<span style=\"color: #007788; font-weight: bold\">int<\/span> j <span style=\"color: #555555\">=<\/span> <span style=\"color: #FF6600\">0<\/span>; j <span style=\"color: #555555\">&lt;<\/span> <span style=\"color: #FF6600\">16<\/span>; <span style=\"color: #555555\">++<\/span>j) {                                    <span style=\"color: #0099FF; font-style: italic\">\/\/ (3)<\/span>\n            myVec.emplace_back(<span style=\"color: #CC3300\">&quot;A short string&quot;<\/span>);\n        }\n    }\n}\n<\/pre><\/div>\n\n\n\n<p>This program allocated a std::array of 2000 bytes : <code>std::array&lt;std::byte, 2000><\/code>. This stack-allocated memory is reused 100 times (line 1). The <code>std::pmr::vector&lt;std::prm::string><\/code> uses the <code>std::pmr::monotonic_buffer_resourc<\/code>e with the upstream memory resource<code> std::pmr::null_memory_resource<\/code> (line 2). Finally, 16 strings are added to the vector.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"612\" height=\"202\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/reuseMemory.png\" alt=\"\" class=\"wp-image-8365\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/reuseMemory.png 612w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/reuseMemory-300x99.png 300w\" sizes=\"auto, (max-width: 612px) 100vw, 612px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">What&#8217;s Next? <\/h2>\n\n\n\n<p>This post ends my min-series about the polymorphic memory resources in C++17. In my next post, I will jump three years further and continue my journey through C++20.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Thanks to polymorphic allocators in C++17, you can optimize your memory allocation. This optimization includes performance and the reuse of memory. Performance The following program is from cppreference.com\/monotonic_buffer_resource. I will explain and extend its performance test to Clang and the MSVC compiler. \/\/ pmrPerformance.cpp \/\/ https:\/\/en.cppreference.com\/w\/cpp\/memory\/monotonic_buffer_resource #include &lt;array&gt; #include &lt;chrono&gt; #include &lt;cstddef&gt; #include &lt;iomanip&gt; #include [&hellip;]<\/p>\n","protected":false},"author":21,"featured_media":8339,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[370],"tags":[556,498],"class_list":["post-8337","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-c-17","tag-allocator","tag-memory"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/8337","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/users\/21"}],"replies":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/comments?post=8337"}],"version-history":[{"count":29,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/8337\/revisions"}],"predecessor-version":[{"id":8481,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/8337\/revisions\/8481"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/8339"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=8337"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=8337"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=8337"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}