{"id":335,"date":"2022-04-24T14:16:14","date_gmt":"2022-04-24T14:16:14","guid":{"rendered":"https:\/\/baldsolutions.com\/?p=335"},"modified":"2022-04-24T14:17:07","modified_gmt":"2022-04-24T14:17:07","slug":"arraypool-reuse-instead-of-create","status":"publish","type":"post","link":"https:\/\/baldsolutions.com\/index.php\/2022\/04\/24\/arraypool-reuse-instead-of-create\/","title":{"rendered":"ArrayPool &#8211; reuse instead of create"},"content":{"rendered":"\n<h1 class=\"wp-block-heading\">Introduction<\/h1>\n\n\n\n<p>There are situations that an array is created over and over again. It is perfectly normal but it creates many temporary objects on the heap. More heap objects means more allocated memory. More allocated memory means more GC overhead. There is, however, <br>a simple and elegant solution to the problem and it is called <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.buffers.arraypool-1?view=net-6.0\" target=\"_blank\" rel=\"noreferrer noopener\" title=\"ArrayPool\">ArrayPool<\/a>.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">ArrayPool<\/h1>\n\n\n\n<p><a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.buffers.arraypool-1?view=net-6.0\" target=\"_blank\" rel=\"noreferrer noopener\" title=\"ArrayPool\">ArrayPool<\/a> is class in a <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.buffers?view=net-6.0\" target=\"_blank\" rel=\"noreferrer noopener\">System.Buffers<\/a> namespace that: &#8220;Provides a resource pool that enables reusing instances of type T[].&#8221; Using <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.buffers.arraypool-1?view=net-6.0\" target=\"_blank\" rel=\"noreferrer noopener\" title=\"ArrayPool\">ArrayPool<\/a> is quite straightforward and in most cases is limited to the <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.buffers.arraypool-1.rent?view=net-6.0#system-buffers-arraypool-1-rent(system-int32)\" target=\"_blank\" rel=\"noreferrer noopener\" title=\"Rent\">Rent<\/a> and <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.buffers.arraypool-1.return?view=net-6.0#system-buffers-arraypool-1-return(-0()-system-boolean)\" target=\"_blank\" rel=\"noreferrer noopener\" title=\"Return\">Return<\/a> methods. First method (as name suggests) rents an array from the pool and the latter one returns the array if it is not needed anymore. There is a great speech about high-performance patterns in C# <a href=\"https:\/\/www.youtube.com\/watch?v=3r6gbZFRDHs&amp;ab_channel=FestGroup\" target=\"_blank\" rel=\"noreferrer noopener\" title=\"here\">here<\/a> (pooling starts at 9:50).<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Example<\/h1>\n\n\n\n<p>Let&#8217;s consider the following <code>ArrayExecutor<\/code> class:<\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code>public class ArrayExecutor\r\n{\r\n    private readonly int _size;\r\n    private readonly Random _random;\r\n\r\n    public ArrayExecutor(int size)\r\n    {\r\n        _random = new Random();\r\n        _size = size;\r\n    }\r\n\r\n    public void ArrayLoop()\r\n    {\r\n        var array = new int&#91;_size];\r\n\r\n        for (int i = 0; i &lt; _size; i++)\r\n            array&#91;i] = _random.Next(100);\r\n\r\n        var minMax = new int&#91;2]\r\n        {\r\n            array.Min(), array.Max()\r\n        };\r\n\r\n        Process(minMax);\r\n    }\r\n\r\n    public void ArrayPoolLoop()\r\n    {\r\n        var array = ArrayPool&lt;int>.Shared.Rent(_size);\r\n\r\n        for (int i = 0; i &lt; _size; i++)\r\n            array&#91;i] = _random.Next(100);\r\n\r\n        var minMax = new int&#91;2]\r\n        {\r\n            array.Min(), array.Max()\r\n        };\r\n\r\n        Process(minMax);\r\n\r\n        ArrayPool&lt;int>.Shared.Return(array);\r\n    }\r\n\r\n    private void Process(int&#91;] array)\r\n    {\r\n        \/\/ some computations here\r\n    }\r\n}<\/code><\/pre>\n\n\n\n<p>The class consists of two public methods: <code>ArrayLoop<\/code> and <code>ArrayPoolLoop<\/code>. First method uses the new() operator to create an array, whereas the latter uses <code>ArrayPool&lt;int>.Shared<\/code>. <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.buffers.arraypool-1.shared?view=net-6.0\" target=\"_blank\" rel=\"noreferrer noopener\" title=\"Shared\">Shared<\/a> is a property of the ArrayPool&lt;T> that provides a default implementation of the ArrayPool. Once the array is created we populated it with some random numbers. Then we calculate min and max and we don&#8217;t need the array anymore. As you can see, the <code>ArrayPoolLoop<\/code> rents an array and then returns it to the pool. <\/p>\n\n\n\n<p>NOTE: the <code>Rent<\/code> method returns an array that is at least the requested length! (e.g. Rent(10) returns an array 16 elements)<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Benchmark<\/h1>\n\n\n\n<p>Let&#8217;s look at the following benchmark result:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"873\" height=\"299\" src=\"https:\/\/baldsolutions.com\/wp-content\/uploads\/2022\/04\/image-1.png\" alt=\"\" class=\"wp-image-344\" srcset=\"https:\/\/baldsolutions.com\/wp-content\/uploads\/2022\/04\/image-1.png 873w, https:\/\/baldsolutions.com\/wp-content\/uploads\/2022\/04\/image-1-300x103.png 300w, https:\/\/baldsolutions.com\/wp-content\/uploads\/2022\/04\/image-1-768x263.png 768w\" sizes=\"auto, (max-width: 873px) 100vw, 873px\" \/><\/figure><\/div>\n\n\n\n<p>This time the last column is crucial for us. As you can see, allocations are tremendously greater for the ArrayLoop method. The ArrayPoolLoop method barely allocates memory.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Summary<\/h1>\n\n\n\n<p>To sum up, ArrayPool is definitely useful in terms of reducing allocation. Reducing allocations is an important topic in the .NET environment. It might be beneficial to be aware of the possible solutions  in terms of reducing memory consumption, hence I highly recommend to do some experiments with the ArrayPool.<\/p>\n\n\n\n<p>As always I&#8217;ve prepared an example and you can find it on my <a href=\"https:\/\/github.com\/tglowka\/baldsolutions\/tree\/master\/.NET\" target=\"_blank\" rel=\"noreferrer noopener\" title=\"github\">github<\/a>, project: <a href=\"https:\/\/github.com\/tglowka\/baldsolutions\/tree\/master\/.NET\/arraypool\" target=\"_blank\" rel=\"noreferrer noopener\" title=\"arraypool\">arraypool<\/a>, benchmark project: <a href=\"https:\/\/github.com\/tglowka\/baldsolutions\/tree\/master\/.NET\/arraypool-benchmark\" target=\"_blank\" rel=\"noreferrer noopener\">arraypool-benchmark<\/a>. <br>I encourage you to go through the code, debug it and try to test your own scenarios.<\/p>\n\n\n\n<p>Have a nice day, bye!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction There are situations that an array is created over and over again. It is perfectly normal but it creates many temporary objects on the&#8230;<\/p>\n<div class=\"more-link-wrapper\"><a class=\"more-link\" href=\"https:\/\/baldsolutions.com\/index.php\/2022\/04\/24\/arraypool-reuse-instead-of-create\/\">Continue reading<span class=\"screen-reader-text\">ArrayPool &#8211; reuse instead of create<\/span><\/a><\/div>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[2],"tags":[],"class_list":["post-335","post","type-post","status-publish","format-standard","hentry","category-net","entry"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/baldsolutions.com\/index.php\/wp-json\/wp\/v2\/posts\/335","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/baldsolutions.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/baldsolutions.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/baldsolutions.com\/index.php\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/baldsolutions.com\/index.php\/wp-json\/wp\/v2\/comments?post=335"}],"version-history":[{"count":14,"href":"https:\/\/baldsolutions.com\/index.php\/wp-json\/wp\/v2\/posts\/335\/revisions"}],"predecessor-version":[{"id":350,"href":"https:\/\/baldsolutions.com\/index.php\/wp-json\/wp\/v2\/posts\/335\/revisions\/350"}],"wp:attachment":[{"href":"https:\/\/baldsolutions.com\/index.php\/wp-json\/wp\/v2\/media?parent=335"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/baldsolutions.com\/index.php\/wp-json\/wp\/v2\/categories?post=335"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/baldsolutions.com\/index.php\/wp-json\/wp\/v2\/tags?post=335"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}