packages feed

circular-0.3.0: bench/Bench.hs

-- |
-- Module      :  Main
-- Description :  Benchmark circular stacks
-- Copyright   :  (c) Dominik Schrempf, 2020
-- License     :  GPL-3.0-or-later
--
-- Maintainer  :  dominik.schrempf@gmail.com
-- Stability   :  unstable
-- Portability :  portable
--
-- Creation date: Sat Jun 20 21:12:38 2020.
module Main
  ( main,
  )
where

import Control.Monad.ST
import Criterion.Main
import Data.Foldable
import qualified Data.Stack.Circular as C
import qualified Data.Vector as V
import qualified Data.Vector.Unboxed as U

-- When using foldl or foldl', list is much slower than cstack.

listFoldL :: Int -> Int
listFoldL l = sum $ take 1000 $ foldl (flip (:)) [] [0 .. l]

cstackV :: Int -> Int
cstackV l = runST $ do
  c <- C.replicate 1000 0 :: ST s (C.MStack V.Vector s Int)
  c' <- foldlM (flip C.push) c [0 .. l]
  C.sum c'

cstackU :: Int -> Int
cstackU l = runST $ do
  c <- C.replicate 1000 0 :: ST s (C.MStack U.Vector s Int)
  c' <- foldlM (flip C.push) c [0 .. l]
  C.sum c'

-- When using foldr, cstack is slower by far. This is because list are lazy.

main :: IO ()
main = do
  let l = 1000000 :: Int
  print $ listFoldL l
  print $ cstackU l
  defaultMain
    [ bench "list, foldl" $ whnf listFoldL l,
      bench "cstack, foldl" $ whnf cstackV l,
      bench "cstack unboxed, foldl" $ whnf cstackU l
    ]

-- benchmarking list, foldl
-- time                 81.05 ms   (77.39 ms .. 85.31 ms)
--                      0.995 R²   (0.989 R² .. 0.999 R²)
-- mean                 86.91 ms   (83.37 ms .. 96.53 ms)
-- std dev              9.154 ms   (2.550 ms .. 15.87 ms)
-- variance introduced by outliers: 29% (moderately inflated)

-- benchmarking cstack, foldl
-- time                 14.92 ms   (14.82 ms .. 14.98 ms)
--                      1.000 R²   (1.000 R² .. 1.000 R²)
-- mean                 15.08 ms   (14.99 ms .. 15.55 ms)
-- std dev              464.1 μs   (31.62 μs .. 1.007 ms)
-- variance introduced by outliers: 11% (moderately inflated)

-- benchmarking cstack unboxed, foldl
-- time                 13.70 ms   (13.64 ms .. 13.77 ms)
--                      1.000 R²   (1.000 R² .. 1.000 R²)
-- mean                 13.66 ms   (13.64 ms .. 13.69 ms)
-- std dev              62.64 μs   (44.97 μs .. 86.20 μs)