packages feed

circular-0.2.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                 196.5 ms   (169.7 ms .. 219.9 ms)
--                      0.983 R²   (0.933 R² .. 1.000 R²)
-- mean                 213.9 ms   (197.8 ms .. 238.8 ms)
-- std dev              25.51 ms   (10.44 ms .. 37.57 ms)
-- variance introduced by outliers: 31% (moderately inflated)

-- benchmarking cstack, foldl
-- time                 18.65 ms   (18.11 ms .. 19.24 ms)
--                      0.993 R²   (0.983 R² .. 0.999 R²)
-- mean                 18.46 ms   (18.13 ms .. 18.99 ms)
-- std dev              979.7 μs   (565.1 μs .. 1.446 ms)
-- variance introduced by outliers: 21% (moderately inflated)

-- benchmarking cstack unboxed, foldl
-- time                 13.97 ms   (13.91 ms .. 14.05 ms)
--                      1.000 R²   (1.000 R² .. 1.000 R²)
-- mean                 13.98 ms   (13.95 ms .. 14.02 ms)
-- std dev              86.51 μs   (61.56 μs .. 120.9 μs)