streamly-0.11.0: benchmark/Streamly/Benchmark/Data/Array/Common.hs
-------------------------------------------------------------------------------
-- Benchmark helpers
-------------------------------------------------------------------------------
{-# INLINE benchIO #-}
benchIO :: NFData b => String -> (Int -> IO a) -> (a -> b) -> Benchmark
benchIO name src f = bench name $ nfIO $
(randomRIO (1,1) >>= src) <&> f
{-# INLINE benchPureSink #-}
benchPureSink :: NFData b => Int -> String -> (Stream Int -> b) -> Benchmark
benchPureSink value name = benchIO name (sourceIntFromTo value)
{-# 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 => Int -> String -> (Stream Int -> IO b) -> Benchmark
benchIOSink value name = benchIO' name (sourceIntFromTo value)
-------------------------------------------------------------------------------
-- Bench Ops
-------------------------------------------------------------------------------
{-# INLINE sourceUnfoldr #-}
sourceUnfoldr :: MonadIO m => Int -> Int -> m (Stream Int)
sourceUnfoldr value n = S.fold (A.createOf value) $ S.unfoldr step n
where
step cnt =
if cnt > n + value
then Nothing
else Just (cnt, cnt + 1)
{-# INLINE sourceIntFromTo #-}
sourceIntFromTo :: MonadIO m => Int -> Int -> m (Stream Int)
sourceIntFromTo value n = S.fold (A.createOf value) $ S.enumerateFromTo n (n + value)
{-# INLINE sourceFromList #-}
sourceFromList :: MonadIO m => Int -> Int -> m (Stream Int)
sourceFromList value n = S.fold (A.createOf value) $ S.fromList [n..n+value]
-------------------------------------------------------------------------------
-- Transformation
-------------------------------------------------------------------------------
{-# INLINE composeN #-}
composeN :: P.Monad m
=> Int -> (Stream Int -> m (Stream Int)) -> Stream Int -> m (Stream Int)
composeN n f x =
case n of
1 -> f x
2 -> f x P.>>= f
3 -> f x P.>>= f P.>>= f
4 -> f x P.>>= f P.>>= f P.>>= f
_ -> undefined
{-# INLINE scanl' #-}
{-# INLINE scanl1' #-}
{-# INLINE map #-}
scanl' , scanl1', map
:: MonadIO m => Int -> Int -> Stream Int -> m (Stream Int)
{-# INLINE onArray #-}
onArray
:: MonadIO m => Int -> (Stream.Stream m Int -> Stream.Stream m Int)
-> Stream Int
-> m (Stream Int)
onArray value f arr = S.fold (A.createOf value) $ f $ S.unfold A.reader arr
scanl' value n = composeN n $ onArray value $ S.scanl (Scanl.mkScanl (+) 0)
scanl1' value n = composeN n $ onArray value $ Stream.scanl1' (+)
map value n = composeN n $ onArray value $ fmap (+1)
-- map n = composeN n $ A.map (+1)
{-# INLINE eqInstance #-}
eqInstance :: Stream Int -> Bool
eqInstance src = src == src
{-# INLINE eqInstanceNotEq #-}
eqInstanceNotEq :: Stream Int -> Bool
eqInstanceNotEq src = src P./= src
{-# INLINE ordInstance #-}
ordInstance :: Stream Int -> Bool
ordInstance src = src P.< src
{-# INLINE ordInstanceMin #-}
ordInstanceMin :: Stream Int -> Stream Int
ordInstanceMin src = P.min src src
{-# INLINE showInstance #-}
showInstance :: Stream Int -> P.String
showInstance = P.show
{-# INLINE pureFoldl' #-}
pureFoldl' :: MonadIO m => Stream Int -> m Int
pureFoldl' = S.fold (Fold.foldl' (+) 0) . S.unfold A.reader
-------------------------------------------------------------------------------
-- Elimination
-------------------------------------------------------------------------------
{-# INLINE unfoldReadDrain #-}
unfoldReadDrain :: MonadIO m => Stream Int -> m ()
unfoldReadDrain = S.fold Fold.drain . S.unfold A.reader
{-# INLINE toStreamRevDrain #-}
toStreamRevDrain :: MonadIO m => Stream Int -> m ()
toStreamRevDrain = S.fold Fold.drain . A.readRev
-------------------------------------------------------------------------------
-- Bench groups
-------------------------------------------------------------------------------
common_o_1_space_generation :: Int -> [Benchmark]
common_o_1_space_generation value =
[ bgroup
"generation"
[ benchIOSrc "writeN . intFromTo" (sourceIntFromTo value)
, benchIOSrc
"fromList . intFromTo"
(sourceIntFromToFromList value)
, benchIOSrc "writeN . unfoldr" (sourceUnfoldr value)
, benchIOSrc "writeN . fromList" (sourceFromList value)
, benchPureSink value "show" showInstance
]
]
common_o_1_space_elimination :: Int -> [Benchmark]
common_o_1_space_elimination value =
[ bgroup "elimination"
[ benchPureSink value "id" id
, benchPureSink value "==" eqInstance
, benchPureSink value "/=" eqInstanceNotEq
, benchPureSink value "<" ordInstance
, benchPureSink value "min" ordInstanceMin
, benchIOSink value "foldl'" pureFoldl'
, benchIOSink value "read" unfoldReadDrain
, benchIOSink value "toStreamRev" toStreamRevDrain
]
]
common_o_n_heap_serial :: Int -> [Benchmark]
common_o_n_heap_serial value =
[ bgroup "elimination"
[
-- Converting the stream to an array
benchFold "writeN" (S.fold (A.createOf value))
(P.sourceUnfoldrM value)
]
]
common_o_1_space_transformation :: Int -> [Benchmark]
common_o_1_space_transformation value =
[ bgroup "transformation"
[ benchIOSink value "scanl'" (scanl' value 1)
, benchIOSink value "scanl1'" (scanl1' value 1)
, benchIOSink value "map" (map value 1)
]
]
common_o_1_space_transformationX4 :: Int -> [Benchmark]
common_o_1_space_transformationX4 value =
[ bgroup "transformationX4"
[ benchIOSink value "scanl'" (scanl' value 4)
, benchIOSink value "scanl1'" (scanl1' value 4)
, benchIOSink value "map" (map value 4)
]
]
commonBenchmarks :: Int -> [Benchmark]
commonBenchmarks size =
[ bgroup (o_1_space_prefix moduleName) $ concat
[ common_o_1_space_generation size
, common_o_1_space_elimination size
, common_o_1_space_transformation size
, common_o_1_space_transformationX4 size
]
, bgroup (o_n_space_prefix moduleName) $
common_o_n_heap_serial size
]