title: Why allocation on ArrayPool is faster then allocation on Stack?
body: <p>I have following benchmark which read string from file using Stack allocation, Heap allocation and ArrayPool allocation. </p>
  
  <p>I would expect that Stack allocation is fastest, because it is just stack pointer increment, but according to benchmark ArrayPool is slightly faster.</p>
  
  <p>How it is possible?</p>
  
  <pre><code>static void Main(string[] args)
  {         
       BenchmarkRunner.Run&lt;BenchmarkRead&gt;();          
  }
  
  using BenchmarkDotNet.Attributes;
  using System;
  using System.Buffers;
  using System.IO;
  using System.Linq;
  
  namespace RealTime.Benchmark
  {
  [MemoryDiagnoser]
  public class BenchmarkRead
  {
      const string TestFile = "TestFiles/animals.txt";
  
      public BenchmarkRead()
      {
          Directory.CreateDirectory(Path.GetDirectoryName(TestFile));
          // cca 100 KB of text
          string content = string.Concat(Enumerable.Repeat("dog,cat,spider,cat,bird,", 4000));
          File.WriteAllText(TestFile, content);
      }
  
      [Benchmark]
      public void ReadFileOnPool() =&gt; ReadFileOnPool(TestFile);
  
      [Benchmark]
      public void ReadFileOnHeap() =&gt; ReadFileOnHeap(TestFile);
  
      [Benchmark]
      public void ReadFileOnStack() =&gt; ReadFileOnStack(TestFile);
  
      public void ReadFileOnHeap(string filename)
      {
          string text = File.ReadAllText(filename);
          // ....call parse
      }
  
      public void ReadFileOnStack(string filename)
      {
          Span&lt;byte&gt; span = stackalloc byte[1024 * 200];
          using (var stream = File.OpenRead(filename))
          {
              int count = stream.Read(span);
              if (count == span.Length)
                  throw new Exception($"Buffer size {span.Length} too small, use array pooling.");
              span = span.Slice(0, count);
              // ....call parse
          }
      }
  
      public void ReadFileOnPool(string filename)
      {
          ArrayPool&lt;byte&gt; pool = ArrayPool&lt;byte&gt;.Shared;
          using (var stream = File.OpenRead(filename))
          {
              long len = stream.Length;
              byte[] buffer = pool.Rent((int)len);
              try
              {
                  int count = stream.Read(buffer, 0, (int)len);
                  if (count != len)
                      throw new Exception($"{count} != {len}");
  
                  Span&lt;byte&gt; span = new Span&lt;byte&gt;(buffer).Slice(0, count);
                  // ....call parse
              }
              finally
              {
                  pool.Return(buffer);
              }
          }
      }
  }
  }
  </code></pre>
  
  <p>Results:</p>
  
  <pre><code>|          Method |     Mean | Gen 0/1k Op | Gen 2/1k Op |Al. memory/Op|
  |---------------- |---------:|------------:|------------:|------------:|
  |  ReadFileOnPool | 109.9 us |      0.1221 |           - |       480 B |
  |  ReadFileOnHeap | 506.0 us |     87.8906 |     58.5938 |    393440 B |
  | ReadFileOnStack | 115.2 us |      0.1221 |           - |       480 B |
  </code></pre>