packages feed

streamly-0.7.1: benchmark/Streamly/Benchmark/Data/SmallArray.hs

-- |
-- Module      : Main
-- Copyright   : (c) 2019 Composewell Technologies
--
-- License     : BSD-3-Clause
-- Maintainer  : streamly@composewell.com
-- Stability   : experimental
-- Portability : GHC

{-# LANGUAGE CPP #-}

module Main (main) where

import Control.DeepSeq (NFData(..), deepseq)
import System.Random (randomRIO)

import qualified Streamly.Benchmark.Data.SmallArrayOps as Ops
import qualified Streamly.Internal.Data.SmallArray as A
import qualified Streamly.Prelude as S

import Gauge

-------------------------------------------------------------------------------
--
-------------------------------------------------------------------------------

{-# INLINE benchIO #-}
benchIO :: NFData b => String -> (Int -> IO a) -> (a -> b) -> Benchmark
benchIO name src f = bench name $ nfIO $
    randomRIO (1,1) >>= src >>= return . f

-- Drain a source that generates an array in the IO monad
{-# INLINE benchIOSrc #-}
benchIOSrc :: (NFData a)
    => String -> (Int -> IO (Ops.Stream a)) -> Benchmark
benchIOSrc name src = benchIO name src id

{-# INLINE benchPureSink #-}
benchPureSink :: NFData b => String -> (Ops.Stream Int -> b) -> Benchmark
benchPureSink name f = benchIO name Ops.sourceIntFromTo f

{-# INLINE benchIO' #-}
benchIO' :: NFData b => String -> (Int -> IO a) -> (a -> IO b) -> Benchmark
benchIO' name src f = bench name $ nfIO $
    randomRIO (1,1) >>= src >>= f

{-# INLINE benchIOSink #-}
benchIOSink :: NFData b => String -> (Ops.Stream Int -> IO b) -> Benchmark
benchIOSink name f = benchIO' name Ops.sourceIntFromTo f

mkString :: String
mkString =
    "fromListN " ++
    show (Ops.value + 1) ++ " [1" ++ concat (replicate Ops.value ",1") ++ "]"

main :: IO ()
main =
  defaultMain
    [ bgroup "SmallArray"
     [  bgroup "generation"
        [ benchIOSrc "writeN . intFromTo" Ops.sourceIntFromTo
        , benchIOSrc "fromList . intFromTo" Ops.sourceIntFromToFromList
        , benchIOSrc "writeN . unfoldr" Ops.sourceUnfoldr
        , benchIOSrc "writeN . fromList" Ops.sourceFromList
        , mkString `deepseq` (bench "read" $ nf Ops.readInstance mkString)
        , benchPureSink "show" Ops.showInstance
        ]
      , bgroup "elimination"
        [ benchPureSink "id" id
        , benchPureSink "==" Ops.eqInstance
        , benchPureSink "/=" Ops.eqInstanceNotEq
        , benchPureSink "<" Ops.ordInstance
        , benchPureSink "min" Ops.ordInstanceMin
        -- length is used to check for foldr/build fusion
        -- , benchPureSink "length . IsList.toList" (length . GHC.toList)
        , benchIOSink "foldl'" Ops.pureFoldl'
        , benchIOSink "read" (S.drain . S.unfold A.read)
        , benchIOSink "toStreamRev" (S.drain . A.toStreamRev)
#ifdef DEVBUILD
        , benchPureSink "foldable/foldl'" Ops.foldableFoldl'
        , benchPureSink "foldable/sum" Ops.foldableSum
#endif
        ]
      , bgroup "transformation"
        [ benchIOSink "scanl'" (Ops.scanl' 1)
        , benchIOSink "scanl1'" (Ops.scanl1' 1)
        , benchIOSink "map" (Ops.map 1)
        ]
      , bgroup "transformationX4"
        [ benchIOSink "scanl'" (Ops.scanl' 4)
        , benchIOSink "scanl1'" (Ops.scanl1' 4)
        , benchIOSink "map" (Ops.map 4)
        ]
    ]
    ]