title: Benchmarking IO action with Criterion
body: <p>I want to know how long it takes my program to read a 12.9MB <code>.wav</code> file into memory. The function that reads a file into memory looks as follows:</p>
  
  <pre><code>import qualified Data.ByteString        as BS
  
  getSamplesFromFileAsBS :: FilePath -&gt; IO (BS.ByteString)
  </code></pre>
  
  <p>It takes the name of the file and returns the samples as a <code>ByteString</code>. It also performs some other validity checks on the data and ignores the header information. I read the <code>ByteString</code> of samples into memory using <code>ByteString.hGet</code>.</p>
  
  <p>If I now benchmark this function with a 12.9MB file, using <code>Criterion</code>:</p>
  
  <pre><code>bencher :: FilePath -&gt; IO ()
  bencher fp = defaultMain [
    bench "Reading all the samples from a file." $ nfIO (getSamplesFromFileAsBS fp)
    ]
  </code></pre>
  
  <p>I get the following result:</p>
  
  <pre><code>benchmarking Reading all the samples from a file.
  time                 3.617 ms   (3.520 ms .. 3.730 ms)
                       0.989 R²   (0.981 R² .. 0.994 R²)
  mean                 3.760 ms   (3.662 ms .. 3.875 ms)
  std dev              354.0 μs   (259.9 μs .. 552.5 μs)
  variance introduced by outliers: 62% (severely inflated)
  </code></pre>
  
  <p>It seems to load 12.9MB into memory in 3.617ms. This doesn't seem realistic since it indicates that my SSD can read 3+GB/s, which is not the case at all. What am I doing wrong?</p>
  
  <p>I decided to try this another (more naive) way, by manually measuring the time difference:</p>
  
  <pre><code>runBenchmarks :: FilePath -&gt; IO ()
  runBenchmarks fp = do
    start &lt;- getCurrentTime
    samplesBS &lt;- getSamplesFromFileAsBS fp
    end &lt;- samplesBS `deepseq` getCurrentTime
    print (diffUTCTime end start)
  </code></pre>
  
  <p>This gives me the following result: 0.023105s. This is realistic because it would mean my SSD can read at a speed of around 600MB/s. What is wrong with the <code>Criterion</code> result?</p>