streamly-0.11.0: benchmark/Streamly/Benchmark/Data/Stream/Expand.hs
-- |
-- Module : Stream.Expand
-- Copyright : (c) 2018 Composewell Technologies
-- License : BSD-3-Clause
-- Maintainer : streamly@composewell.com
{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE RankNTypes #-}
#ifdef USE_PRELUDE
#endif
#ifdef __HADDOCK_VERSION__
#undef INSPECTION
#endif
#ifdef INSPECTION
{-# LANGUAGE TemplateHaskell #-}
{-# OPTIONS_GHC -fplugin Test.Inspection.Plugin #-}
#endif
module Stream.Expand (benchmarks) where
#ifdef INSPECTION
import GHC.Types (SPEC(..))
import Test.Inspection
import qualified Streamly.Internal.Data.Stream as D
#endif
import qualified Stream.Common as Common
import qualified Streamly.Internal.Data.Unfold as UF
#ifdef USE_PRELUDE
import qualified Streamly.Internal.Data.Stream.IsStream as S
import Streamly.Benchmark.Prelude
( sourceFoldMapM, sourceFoldMapWith, sourceFoldMapWithM
, sourceFoldMapWithStream, concatFoldableWith, concatForFoldableWith)
#else
import Streamly.Data.Stream (Stream)
import Streamly.Data.Unfold (Unfold)
import qualified Streamly.Internal.Data.Stream as S
import qualified Streamly.Internal.Data.Unfold as Unfold
import qualified Streamly.Internal.Data.Fold as Fold
import qualified Streamly.Internal.Data.Stream as Stream
import qualified Streamly.Internal.Data.StreamK as StreamK
#endif
import Test.Tasty.Bench
import Stream.Common
import Streamly.Benchmark.Common
import Prelude hiding (concatMap)
-------------------------------------------------------------------------------
-- Multi-Stream
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- Appending
-------------------------------------------------------------------------------
{-# INLINE serial2 #-}
serial2 :: Int -> Int -> IO ()
serial2 count n =
drain $
Common.append
(sourceUnfoldrM count n)
(sourceUnfoldrM count (n + 1))
{-# INLINE serial4 #-}
serial4 :: Int -> Int -> IO ()
serial4 count n =
drain $
Common.append
(Common.append
(sourceUnfoldrM count n)
(sourceUnfoldrM count (n + 1)))
(Common.append
(sourceUnfoldrM count (n + 2))
(sourceUnfoldrM count (n + 3)))
o_1_space_joining :: Int -> [Benchmark]
o_1_space_joining value =
[ bgroup "joining"
[ benchIOSrc1 "serial (2,x/2)" (serial2 (value `div` 2))
, benchIOSrc1 "serial (2,2,x/4)" (serial4 (value `div` 4))
]
]
-------------------------------------------------------------------------------
-- Concat Foldable containers
-------------------------------------------------------------------------------
#ifdef USE_PRELUDE
o_1_space_concatFoldable :: Int -> [Benchmark]
o_1_space_concatFoldable value =
[ bgroup "concat-foldable"
[ benchIOSrc "foldMapWith (<>) (List)"
(sourceFoldMapWith value)
, benchIOSrc "foldMapWith (<>) (Stream)"
(sourceFoldMapWithStream value)
, benchIOSrc "foldMapWithM (<>) (List)"
(sourceFoldMapWithM value)
, benchIOSrc "S.concatFoldableWith (<>) (List)"
(concatFoldableWith value)
, benchIOSrc "S.concatForFoldableWith (<>) (List)"
(concatForFoldableWith value)
, benchIOSrc "foldMapM (List)" (sourceFoldMapM value)
]
]
#endif
-------------------------------------------------------------------------------
-- Concat
-------------------------------------------------------------------------------
-- concatMap unfoldrM/unfoldrM
{-# INLINE concatMap #-}
concatMap :: Int -> Int -> Int -> IO ()
concatMap outer inner n =
drain $ S.concatMap
(\_ -> sourceUnfoldrM inner n)
(sourceUnfoldrM outer n)
{-# INLINE concatMapViaUnfoldEach #-}
concatMapViaUnfoldEach :: Int -> Int -> Int -> IO ()
concatMapViaUnfoldEach outer inner n =
drain $ cmap
(\_ -> sourceUnfoldrM inner n)
(sourceUnfoldrM outer n)
where
cmap f = Stream.unfoldEach (UF.lmap f UF.fromStream)
{-# INLINE concatMapM #-}
concatMapM :: Int -> Int -> Int -> IO ()
concatMapM outer inner n =
drain $ S.concatMapM
(\_ -> return $ sourceUnfoldrM inner n)
(sourceUnfoldrM outer n)
#ifdef INSPECTION
inspect $ hasNoTypeClasses 'concatMap
inspect $ 'concatMap `hasNoType` ''SPEC
#endif
-- concatMap unfoldr/unfoldr
{-# INLINE concatMapPure #-}
concatMapPure :: Int -> Int -> Int -> IO ()
concatMapPure outer inner n =
drain $ S.concatMap
(\_ -> sourceUnfoldr inner n)
(sourceUnfoldr outer n)
#ifdef INSPECTION
#if __GLASGOW_HASKELL__ >= 906
inspect $ hasNoTypeClassesExcept 'concatMapPure [''Applicative]
#else
inspect $ hasNoTypeClasses 'concatMapPure
#endif
inspect $ 'concatMapPure `hasNoType` ''SPEC
#endif
{-# INLINE sourceUnfoldrMUnfold #-}
sourceUnfoldrMUnfold :: Monad m => Int -> Int -> Unfold m Int Int
sourceUnfoldrMUnfold size start = UF.unfoldrM step
where
step i =
return
$ if i < start + size
then Just (i, i + 1)
else Nothing
{-# INLINE unfoldEach #-}
unfoldEach :: Int -> Int -> Int -> IO ()
unfoldEach outer inner start = drain $
-- XXX the replicateM takes much more time compared to unfoldrM, is there
-- a perf issue or this is just because of accessing outer loop variables?
-- S.unfoldEach (UF.lmap ((inner,) . return) UF.replicateM)
S.unfoldEach (sourceUnfoldrMUnfold inner start)
$ sourceUnfoldrM outer start
#ifdef INSPECTION
inspect $ hasNoTypeClasses 'unfoldEach
inspect $ 'unfoldEach `hasNoType` ''D.ConcatMapUState
inspect $ 'unfoldEach `hasNoType` ''SPEC
#endif
{-# INLINE unfoldEach2 #-}
unfoldEach2 :: Int -> Int -> Int -> IO ()
unfoldEach2 outer inner start = drain $
S.unfoldEach (UF.carry (sourceUnfoldrMUnfold inner start))
$ sourceUnfoldrM outer start
{-# INLINE unfoldEach3 #-}
unfoldEach3 :: Int -> Int -> IO ()
unfoldEach3 linearCount start = drain $ do
S.unfoldEach (UF.carry (UF.lmap snd (sourceUnfoldrMUnfold nestedCount3 start)))
$ S.unfoldEach (UF.carry (sourceUnfoldrMUnfold nestedCount3 start))
$ sourceUnfoldrM nestedCount3 start
where
nestedCount3 = round (fromIntegral linearCount**(1/3::Double))
{-# INLINE unfoldCross #-}
unfoldCross :: Int -> Int -> Int -> IO ()
unfoldCross outer inner start = drain $
Stream.unfoldCross
UF.identity
(sourceUnfoldrM outer start)
(sourceUnfoldrM inner start)
o_1_space_concat :: Int -> [Benchmark]
o_1_space_concat value = sqrtVal `seq`
[ bgroup "concat"
[ benchIOSrc1 "concatMapPure outer=Max inner=1"
(concatMapPure value 1)
, benchIOSrc1 "concatMapPure outer=inner=(sqrt Max)"
(concatMapPure sqrtVal sqrtVal)
, benchIOSrc1 "concatMapPure outer=1 inner=Max"
(concatMapPure 1 value)
, benchIOSrc1 "concatMap outer=max inner=1"
(concatMap value 1)
, benchIOSrc1 "concatMap outer=inner=(sqrt Max)"
(concatMap sqrtVal sqrtVal)
, benchIOSrc1 "concatMap outer=1 inner=Max"
(concatMap 1 value)
-- This is for comparison with foldMapWith
, benchIOSrc "concatMapId outer=max inner=1 (fromFoldable)"
(S.concatMap id . sourceConcatMapId value)
, benchIOSrc1 "concatMapM outer=max inner=1"
(concatMapM value 1)
, benchIOSrc1 "concatMapM outer=inner=(sqrt Max)"
(concatMapM sqrtVal sqrtVal)
, benchIOSrc1 "concatMapM outer=1 inner=Max"
(concatMapM 1 value)
, benchIOSrc1 "concatMapViaUnfoldEach outer=max inner=1"
(concatMapViaUnfoldEach value 1)
, benchIOSrc1 "concatMapViaUnfoldEach outer=inner=(sqrt Max)"
(concatMapViaUnfoldEach sqrtVal sqrtVal)
, benchIOSrc1 "concatMapViaUnfoldEach outer=1 inner=Max"
(concatMapViaUnfoldEach 1 value)
, benchIOSrc1 "unfoldCross outer=max inner=1"
(unfoldCross value 1)
, benchIOSrc1 "unfoldCross outer=inner=(sqrt Max)"
(unfoldCross sqrtVal sqrtVal)
, benchIOSrc1 "unfoldCross outer=1 inner=Max"
(unfoldCross 1 value)
-- concatMap vs unfoldEach
, benchIOSrc1 "unfoldEach outer=Max inner=1"
(unfoldEach value 1)
, benchIOSrc1 "unfoldEach outer=inner=(sqrt Max)"
(unfoldEach sqrtVal sqrtVal)
, benchIOSrc1 "unfoldEach outer=1 inner=Max"
(unfoldEach 1 value)
, benchIOSrc1 "unfoldEach2 outer=Max inner=1"
(unfoldEach2 value 1)
, benchIOSrc1 "unfoldEach2 outer=inner=(sqrt Max)"
(unfoldEach2 sqrtVal sqrtVal)
, benchIOSrc1 "unfoldEach2 outer=1 inner=Max"
(unfoldEach2 1 value)
, benchIOSrc1 "unfoldEach3 outer=inner=(cubert Max)"
(unfoldEach3 value)
]
]
where
sqrtVal = round $ sqrt (fromIntegral value :: Double)
-------------------------------------------------------------------------------
-- Applicative
-------------------------------------------------------------------------------
{-# INLINE cross2 #-}
cross2 :: MonadAsync m => Int -> Int -> m ()
cross2 linearCount start = drain $
Stream.crossWith (+)
(sourceUnfoldr nestedCount2 start)
(sourceUnfoldr nestedCount2 start)
where
nestedCount2 = round (fromIntegral linearCount**(1/2::Double))
o_1_space_applicative :: Int -> [Benchmark]
o_1_space_applicative value =
[ bgroup "Applicative"
[ benchIO "(*>)" $ apDiscardFst value
, benchIO "(<*)" $ apDiscardSnd value
, benchIO "(<*>)" $ toNullAp value
, benchIO "liftA2" $ apLiftA2 value
, benchIO "pureDrain2" $ toNullApPure value
, benchIO "pureCross2" $ cross2 value
]
]
-------------------------------------------------------------------------------
-- Monad
-------------------------------------------------------------------------------
o_1_space_monad :: Int -> [Benchmark]
o_1_space_monad value =
[ bgroup "Monad"
[ benchIO "then2" $ monadThen value
, benchIO "drain2" $ toNullM value
, benchIO "drain3" $ toNullM3 value
, benchIO "filterAllOut2" $ filterAllOutM value
, benchIO "filterAllIn2" $ filterAllInM value
, benchIO "filterSome2" $ filterSome value
, benchIO "breakAfterSome2" $ breakAfterSome value
, benchIO "pureDrain2" $ toNullMPure value
, benchIO "pureDrain3" $ toNullM3Pure value
, benchIO "pureFilterAllIn2" $ filterAllInMPure value
, benchIO "pureFilterAllOut2" $ filterAllOutMPure value
]
]
o_n_space_monad :: Int -> [Benchmark]
o_n_space_monad value =
[ bgroup "Monad"
[ benchIO "toList2" $ toListM value
, benchIO "toListSome2" $ toListSome value
]
]
{-# INLINE drainConcatFor1 #-}
drainConcatFor1 :: Monad m => Stream m Int -> m ()
drainConcatFor1 s = drain $ do
Stream.concatFor s $ \x ->
Stream.fromPure $ x + 1
{-# INLINE drainConcatFor #-}
drainConcatFor :: Monad m => Stream m Int -> m ()
drainConcatFor s = drain $ do
Stream.concatFor s $ \x ->
Stream.concatFor s $ \y ->
Stream.fromPure $ x + y
{-# INLINE drainConcatForM #-}
drainConcatForM :: Monad m => Stream m Int -> m ()
drainConcatForM s = drain $ do
Stream.concatForM s $ \x ->
pure $ Stream.concatForM s $ \y ->
pure $ Stream.fromPure $ x + y
{-# INLINE drainConcatFor3 #-}
drainConcatFor3 :: Monad m => Stream m Int -> m ()
drainConcatFor3 s = drain $ do
Stream.concatFor s $ \x ->
Stream.concatFor s $ \y ->
Stream.concatFor s $ \z ->
Stream.fromPure $ x + y + z
{-# INLINE drainConcatFor4 #-}
drainConcatFor4 :: Monad m => Stream m Int -> m ()
drainConcatFor4 s = drain $ do
Stream.concatFor s $ \x ->
Stream.concatFor s $ \y ->
Stream.concatFor s $ \z ->
Stream.concatFor s $ \w ->
Stream.fromPure $ x + y + z + w
{-# INLINE drainConcatFor5 #-}
drainConcatFor5 :: Monad m => Stream m Int -> m ()
drainConcatFor5 s = drain $ do
Stream.concatFor s $ \x ->
Stream.concatFor s $ \y ->
Stream.concatFor s $ \z ->
Stream.concatFor s $ \w ->
Stream.concatFor s $ \u ->
Stream.fromPure $ x + y + z + w + u
{-# INLINE drainConcatFor3M #-}
drainConcatFor3M :: Monad m => Stream m Int -> m ()
drainConcatFor3M s = drain $ do
Stream.concatForM s $ \x ->
pure $ Stream.concatForM s $ \y ->
pure $ Stream.concatForM s $ \z ->
pure $ Stream.fromPure $ x + y + z
{-# INLINE filterAllInConcatFor #-}
filterAllInConcatFor
:: Monad m
=> Stream m Int -> m ()
filterAllInConcatFor s = drain $ do
Stream.concatFor s $ \x ->
Stream.concatFor s $ \y ->
let s1 = x + y
in if s1 > 0
then Stream.fromPure s1
else Stream.nil
{-# INLINE filterAllOutConcatFor #-}
filterAllOutConcatFor
:: Monad m
=> Stream m Int -> m ()
filterAllOutConcatFor s = drain $ do
Stream.concatFor s $ \x ->
Stream.concatFor s $ \y ->
let s1 = x + y
in if s1 < 0
then Stream.fromPure s1
else Stream.nil
o_1_space_bind :: Int -> [Benchmark]
o_1_space_bind streamLen =
[ bgroup "concatFor"
[ benchFold "drain1" drainConcatFor1 (sourceUnfoldrM streamLen)
, benchFold "drain2" drainConcatFor (sourceUnfoldrM streamLen2)
, benchFold "drain3" drainConcatFor3 (sourceUnfoldrM streamLen3)
, benchFold "drain4" drainConcatFor4 (sourceUnfoldrM streamLen4)
, benchFold "drain5" drainConcatFor5 (sourceUnfoldrM streamLen5)
, benchFold "drainM2" drainConcatForM (sourceUnfoldrM streamLen2)
, benchFold "drainM3" drainConcatFor3M (sourceUnfoldrM streamLen3)
, benchFold "filterAllIn2" filterAllInConcatFor (sourceUnfoldrM streamLen2)
, benchFold "filterAllOut2" filterAllOutConcatFor (sourceUnfoldrM streamLen2)
]
]
where
streamLen2 = round (fromIntegral streamLen**(1/2::Double)) -- double nested loop
streamLen3 = round (fromIntegral streamLen**(1/3::Double)) -- triple nested loop
streamLen4 = round (fromIntegral streamLen**(1/4::Double)) -- 4 times nested loop
streamLen5 = round (fromIntegral streamLen**(1/5::Double)) -- 5 times nested loop
-- search space |x| = 1000, |y| = 1000
{-# INLINE boundedInts #-}
boundedInts :: Monad m => Int -> Int -> Stream m Int
boundedInts n _ =
Stream.interleave
(Stream.enumerateFromTo (0 :: Int) n)
(Stream.enumerateFromThenTo (-1) (-2) (-n))
{-# INLINE infiniteInts #-}
infiniteInts :: Monad m => Int -> Int -> Stream m Int
infiniteInts _ _ =
Stream.interleave
(Stream.enumerateFrom (0 :: Int))
(Stream.enumerateFromThen (-1) (-2))
{-# INLINE boundedIntsUnfold #-}
boundedIntsUnfold :: Monad m => Int -> Int -> Unfold m ((), ()) Int
boundedIntsUnfold n _ =
Unfold.interleave
(Unfold.supply (0 :: Int, n) Unfold.enumerateFromTo)
(Unfold.supply (-1, -2, -n) Unfold.enumerateFromThenTo)
{-# INLINE infiniteIntsUnfold #-}
infiniteIntsUnfold :: Monad m => Int -> Int -> Unfold m ((), ()) Int
infiniteIntsUnfold _ _ =
Unfold.interleave
(Unfold.supply (0 :: Int) Unfold.enumerateFrom)
(Unfold.supply (-1, -2) Unfold.enumerateFromThen)
{-# INLINE checkStream #-}
checkStream :: Applicative m =>
Int -> Int -> Stream m (Maybe (Maybe (Int, Int)))
checkStream x y =
let eq1 = x + y == 0
eq2 = x - y == 1994
in if eq1 && eq2
then Stream.fromPure (Just (Just (x,y)))
else if abs x > 1000 && abs y > 1000
then Stream.fromPure (Just Nothing)
else Stream.fromPure Nothing
{-# INLINE checkStreamK #-}
checkStreamK :: Int -> Int -> StreamK.StreamK m (Maybe (Maybe (Int, Int)))
checkStreamK x y =
let eq1 = x + y == 0
eq2 = x - y == 1994
in if eq1 && eq2
then StreamK.fromPure (Just (Just (x,y)))
else if abs x > 1000 && abs y > 1000
then StreamK.fromPure (Just Nothing)
else StreamK.fromPure Nothing
{-# INLINE checkPair #-}
checkPair :: Monad m => (Int, Int) -> m (Maybe (Maybe (Int, Int)))
checkPair (x, y) =
let eq1 = x + y == 0
eq2 = x - y == 1994
in if eq1 && eq2
then pure (Just (Just (x,y)))
else if abs x > 1000 && abs y > 1000
then pure (Just Nothing)
else pure Nothing
result :: Monad m => Stream m (Maybe a) -> m ()
result = Stream.fold (Fold.take 1 Fold.drain) . Stream.catMaybes
fairConcatForEqn :: Monad m => Stream m Int -> m ()
fairConcatForEqn input =
result
$ Stream.fairConcatFor input $ \x ->
Stream.fairConcatForM input $ \y -> do
return $ checkStream x y
fairConcatForEqnK :: Monad m => Stream m Int -> m ()
fairConcatForEqnK input =
let inputK = StreamK.fromStream input
in result
$ StreamK.toStream
$ StreamK.fairConcatFor inputK $ \x ->
StreamK.fairConcatForM inputK $ \y -> do
return $ checkStreamK x y
concatForEqn :: Monad m => Stream m Int -> m ()
concatForEqn input =
result
$ Stream.concatFor input $ \x ->
Stream.concatForM input $ \y -> do
return $ checkStream x y
fairSchedForEqn :: Monad m => Stream m Int -> m ()
fairSchedForEqn input =
result
$ Stream.fairSchedFor input $ \x ->
Stream.fairSchedForM input $ \y -> do
return $ checkStream x y
_schedForEqn :: Monad m => Stream m Int -> m ()
_schedForEqn input =
result
$ Stream.schedFor input $ \x ->
Stream.schedForM input $ \y -> do
return $ checkStream x y
streamCrossEqn :: Monad m => Stream m Int -> m ()
streamCrossEqn input =
result
$ Stream.mapM checkPair
$ Stream.cross input input
fairStreamCrossEqn :: Monad m => Stream m Int -> m ()
fairStreamCrossEqn input =
result
$ Stream.mapM checkPair
$ Stream.fairCross input input
unfoldCrossEqn :: Monad m => Unfold m ((), ()) Int -> m ()
unfoldCrossEqn input =
result
$ Stream.mapM checkPair
$ Stream.unfold (Unfold.cross input input) (undefined, undefined)
fairUnfoldCrossEqn :: Monad m => Unfold m ((), ()) Int -> m ()
fairUnfoldCrossEqn input =
result
$ Stream.mapM checkPair
$ Stream.unfold (Unfold.fairCross input input) (undefined, undefined)
unfoldEachEqn :: Monad m => Unfold m ((), ()) Int -> Stream m Int -> m ()
unfoldEachEqn input ints =
let intu = Unfold.carry $ Unfold.lmap (const (undefined, undefined)) input
in result
$ Stream.mapM checkPair
$ Stream.unfoldEach intu ints
fairUnfoldEachEqn :: Monad m => Unfold m ((), ()) Int -> Stream m Int -> m ()
fairUnfoldEachEqn input ints =
let intu = Unfold.carry $ Unfold.lmap (const (undefined, undefined)) input
in result
$ Stream.mapM checkPair
$ Stream.fairUnfoldEach intu ints
unfoldSchedEqn :: Monad m => Unfold m ((), ()) Int -> Stream m Int -> m ()
unfoldSchedEqn input ints =
let intu = Unfold.carry $ Unfold.lmap (const (undefined, undefined)) input
in result
$ Stream.mapM checkPair
$ Stream.unfoldSched intu ints
fairUnfoldSchedEqn :: Monad m => Unfold m ((), ()) Int -> Stream m Int -> m ()
fairUnfoldSchedEqn input ints =
let intu = Unfold.carry $ Unfold.lmap (const (undefined, undefined)) input
in result
$ Stream.mapM checkPair
$ Stream.fairUnfoldSched intu ints
-- Solve simultaneous equations by exploring all possibilities
o_1_space_equations :: Int -> [Benchmark]
o_1_space_equations _ =
[ bgroup "equations"
[ benchFold "concatFor (bounded)" concatForEqn (boundedInts 1000)
, benchFold "fairConcatFor (bounded)"
fairConcatForEqn (boundedInts 1000)
, benchFold "fairConcatForK (bounded)"
fairConcatForEqnK (boundedInts 1000)
, benchFold "fairConcatFor (infinite)"
fairConcatForEqn (infiniteInts 1000)
, benchFold "fairSchedFor (bounded)"
fairSchedForEqn (boundedInts 1000)
, benchFold "fairSchedFor (infinite)"
fairSchedForEqn (infiniteInts 1000)
, benchFold "streamCross (bounded)"
streamCrossEqn (boundedInts 1000)
, benchFold "fairStreamCross (bounded)"
fairStreamCrossEqn (boundedInts 1000)
, benchFold "fairStreamCross (infinite)"
fairStreamCrossEqn (infiniteInts 1000)
, bench "unfoldCross (bounded)"
$ nfIO $ unfoldCrossEqn (boundedIntsUnfold 1000 0)
, bench "fairUnfoldCross (bounded)"
$ nfIO $ fairUnfoldCrossEqn (boundedIntsUnfold 1000 0)
, bench "fairUnfoldCross (infinite)"
$ nfIO $ fairUnfoldCrossEqn (infiniteIntsUnfold 1000 0)
, benchFold "unfoldEach (bounded)"
(unfoldEachEqn (boundedIntsUnfold 1000 0)) (boundedInts 1000)
, benchFold "fairUnfoldEach (bounded)"
(fairUnfoldEachEqn (boundedIntsUnfold 1000 0)) (boundedInts 1000)
, benchFold "fairUnfoldEach (infinite)"
(fairUnfoldEachEqn (infiniteIntsUnfold 1000 0)) (infiniteInts 1000)
, benchFold "unfoldSched (bounded)"
(unfoldSchedEqn (boundedIntsUnfold 1000 0)) (boundedInts 1000)
, benchFold "fairUnfoldSched (bounded)"
(fairUnfoldSchedEqn (boundedIntsUnfold 1000 0)) (boundedInts 1000)
, benchFold "fairUnfoldSched (infinite)"
(fairUnfoldSchedEqn (infiniteIntsUnfold 1000 0)) (infiniteInts 1000)
]
]
-------------------------------------------------------------------------------
-- Joining
-------------------------------------------------------------------------------
{-
toKv :: Int -> (Int, Int)
toKv p = (p, p)
{-# INLINE joinWith #-}
joinWith :: Common.MonadAsync m =>
((Int -> Int -> Bool) -> Stream m Int -> Stream m Int -> Stream m b)
-> Int
-> Int
-> m ()
joinWith j val i =
drain $ j (==) (sourceUnfoldrM val i) (sourceUnfoldrM val (val `div` 2))
{-# INLINE joinMapWith #-}
joinMapWith :: Common.MonadAsync m =>
(Stream m (Int, Int) -> Stream m (Int, Int) -> Stream m b)
-> Int
-> Int
-> m ()
joinMapWith j val i =
drain
$ j
(fmap toKv (sourceUnfoldrM val i))
(fmap toKv (sourceUnfoldrM val (val `div` 2)))
o_n_heap_buffering :: Int -> [Benchmark]
o_n_heap_buffering value =
[ bgroup "buffered"
[
benchIOSrc1 "joinInnerGeneric (sqrtVal)"
$ joinWith S.joinInnerGeneric sqrtVal
, benchIOSrc1 "joinInner"
$ joinMapWith S.joinInner halfVal
, benchIOSrc1 "joinLeftGeneric (sqrtVal)"
$ joinWith S.joinLeftGeneric sqrtVal
, benchIOSrc1 "joinLeft "
$ joinMapWith S.joinLeft halfVal
, benchIOSrc1 "joinOuterGeneric (sqrtVal)"
$ joinWith S.joinOuterGeneric sqrtVal
, benchIOSrc1 "joinOuter"
$ joinMapWith S.joinOuter halfVal
, benchIOSrc1 "filterInStreamGenericBy (sqrtVal)"
$ joinWith S.filterInStreamGenericBy sqrtVal
, benchIOSrc1 "filterInStreamAscBy"
$ joinMapWith (S.filterInStreamAscBy compare) halfVal
-- Note: schedFor does a bfs scheduling, therefore, can take a lot of
-- memory.
, benchFold "schedFor (bounded)" schedForEqn (boundedInts 1000)
]
]
where
halfVal = value `div` 2
sqrtVal = round $ sqrt (fromIntegral value :: Double)
-}
-------------------------------------------------------------------------------
-- Main
-------------------------------------------------------------------------------
-- In addition to gauge options, the number of elements in the stream can be
-- passed using the --stream-size option.
--
{-# ANN benchmarks "HLint: ignore" #-}
benchmarks :: String -> Int -> [Benchmark]
benchmarks moduleName size =
[ bgroup (o_1_space_prefix moduleName) $ Prelude.concat
[
-- multi-stream
o_1_space_joining size
#ifdef USE_PRELUDE
, o_1_space_concatFoldable size
#endif
, o_1_space_concat size
, o_1_space_applicative size
, o_1_space_monad size
, o_1_space_bind size
, o_1_space_equations size
]
, bgroup (o_n_space_prefix moduleName) $ Prelude.concat
[
-- multi-stream
o_n_space_monad size
]
{-
, bgroup (o_n_heap_prefix moduleName) $
-- multi-stream
o_n_heap_buffering size
-}
]