title: Why is Async version slower than single threaded version?
body: <p>I am reading a large XML file using XmlReader and am exploring potential performance improvements via Async &amp; pipelining. The following initial foray into the world of Async is showing that the Async version (which for all intents and purposes at this point is the equivalent of the Synchronous version) is much slower. <strong>Why would this be?</strong> All I've done is wrapped the &quot;normal&quot; code in an Async block and called it with <code>Async.RunSynchronously</code></p>
  <h1>Code</h1>
  <pre><code>open System
  open System.IO.Compression  // support assembly required + FileSystem
  open System.Xml             // support assembly required
  
  
  let readerNormal (reader:XmlReader) = 
      let temp = ResizeArray&lt;string&gt;()
      while reader.Read() do
          ()
      temp
  
  let readerAsync1 (reader:XmlReader) = 
      async{
          let temp = ResizeArray&lt;string&gt;()
          while reader.Read() do
              ()
          return temp
      }
  
  let readerAsync2 (reader:XmlReader) = 
      async{
          while reader.Read() do
              ()
      }
  
  [&lt;EntryPoint&gt;]
  let main argv = 
  
      let path = @&quot;C:\Temp\LargeTest1000.xlsx&quot;
      use zipArchive = ZipFile.OpenRead path
      let sheetZipEntry = zipArchive.GetEntry(@&quot;xl/worksheets/sheet1.xml&quot;)
  
      let stopwatch = System.Diagnostics.Stopwatch()
      stopwatch.Start()
      let sheetStream = sheetZipEntry.Open()  // again
      use reader = XmlReader.Create(sheetStream)
      let temp1 = readerNormal reader
      stopwatch.Stop()
      printfn &quot;%A&quot; stopwatch.Elapsed
  
      System.GC.Collect()
  
      let stopwatch = System.Diagnostics.Stopwatch()
      stopwatch.Start()
      let sheetStream = sheetZipEntry.Open()  // again
      use reader = XmlReader.Create(sheetStream)
      let temp1 = readerAsync1 reader |&gt; Async.RunSynchronously
      stopwatch.Stop()
      printfn &quot;%A&quot; stopwatch.Elapsed
  
      System.GC.Collect()
  
      let stopwatch = System.Diagnostics.Stopwatch()
      stopwatch.Start()
      let sheetStream = sheetZipEntry.Open()  // again
      use reader = XmlReader.Create(sheetStream)
      readerAsync2 reader |&gt; Async.RunSynchronously
      stopwatch.Stop()
      printfn &quot;%A&quot; stopwatch.Elapsed
  
      printfn &quot;DONE&quot;
      System.Console.ReadLine() |&gt; ignore
      0 // return an integer exit code
  </code></pre>
  <h1>INFO</h1>
  <ol>
  <li><p>I am aware that the above Async code does not do any actual Async work - what I a trying to ascertain here is the overhead of simply making it Async</p>
  </li>
  <li><p>I don't expect it to go faster just because I've wrapped it in an Async. My question is the opposite: why the dramatic (IMHO) slowdown.</p>
  </li>
  </ol>
  <h1>TIMINGS</h1>
  <p>A comment below correctly pointed out that I should provide timings for datasets of various sizes which is implicitly what had led me to be asking this question in the first instance.</p>
  <p>The following are some times based on small vs large datasets. While the absolute values are not too meaningful, the relativities are interesting:</p>
  <p>30 elements (small dataset)</p>
  <blockquote>
  <p>Normal: 00:00:00.0006994</p>
  <p>Async1: 00:00:00.0036529</p>
  <p>Async2: 00:00:00.0014863</p>
  </blockquote>
  <p>(A lot slower but presumably indicative of Async setup costs - this is as expected)</p>
  <p>1.5 million elements</p>
  <blockquote>
  <p>Normal: 00:00:01.5749734</p>
  <p>Async1: 00:00:03.3942754</p>
  <p>Async2: 00:00:03.3760785</p>
  </blockquote>
  <p>(~ 2x slower. Surprised that the difference in timing is not amortized as the dataset gets bigger. If this is the case, then pipelining/parallelization can only improve performance here if you have more than two cores - to outweigh the overhead that I can't explain...)</p>