@@ -23,16 +23,18 @@
24module Streamly.Benchmark.Prelude where
24module Streamly.Benchmark.Prelude where
26−import Control.DeepSeq (NFData)
26+import Control.DeepSeq (NFData(..))
27import Control.Monad (when)
27import Control.Monad (when)
28import Control.Monad.IO.Class (MonadIO(..))
28import Control.Monad.IO.Class (MonadIO(..))
29import Control.Monad.State.Strict (StateT, get, put)
29import Control.Monad.State.Strict (StateT, get, put)
30import Data.Functor.Identity (Identity, runIdentity)
30import Data.Functor.Identity (Identity, runIdentity)
31import Data.IORef (newIORef, modifyIORef')
31import Data.IORef (newIORef, modifyIORef')
32+import Data.Monoid (Last(..))
32import GHC.Generics (Generic)
33import GHC.Generics (Generic)
34+import System.Random (randomRIO)
33import Prelude
35import Prelude
34− (Monad, Int, (+), ($), (.), return, fmap, even, (>), (<=), (==), (>=),
36+ (Monad, String, Int, (+), ($), (.), return, even, (>), (<=), (==), (>=),
35− subtract, undefined, Maybe(..), odd, Bool, not, (>>=), mapM_, curry,
37+ subtract, undefined, Maybe(..), Bool, not, (>>=), curry,
36 maxBound, div, IO, compare, Double, fromIntegral, Integer, (<$>),
38 maxBound, div, IO, compare, Double, fromIntegral, Integer, (<$>),
37 (<*>), flip)
39 (<*>), flip)
38import qualified Prelude as P
40import qualified Prelude as P
@@ -46,6 +48,7 @@ import Test.Inspection
46import qualified Streamly.Internal.Data.Stream.StreamD as D
48import qualified Streamly.Internal.Data.Stream.StreamD as D
51+import Streamly (SerialT, IsStream, wSerially, zipSerially, serially)
49import qualified Streamly as S hiding (runStream)
52import qualified Streamly as S hiding (runStream)
50import qualified Streamly.Prelude as S
53import qualified Streamly.Prelude as S
51import qualified Streamly.Internal.Prelude as Internal
54import qualified Streamly.Internal.Prelude as Internal
@@ -55,6 +58,19 @@ import qualified Streamly.Internal.Data.Pipe as Pipe
55import qualified Streamly.Internal.Data.Stream.Parallel as Par
58import qualified Streamly.Internal.Data.Stream.Parallel as Par
56import Streamly.Internal.Data.Time.Units
59import Streamly.Internal.Data.Time.Units
61+import qualified Streamly.Internal.Data.Sink as Sink
63+import qualified Streamly.Internal.Memory.Array as IA
64+import qualified Streamly.Internal.Data.Fold as IFL
65+import qualified Streamly.Internal.Prelude as IP
67+import qualified NestedOps as Nested
68+import qualified NestedUnfoldOps as NestedUnfold
71+import Streamly.Benchmark.Common
58type Stream m a = S.SerialT m a
74type Stream m a = S.SerialT m a
60-------------------------------------------------------------------------------
76-------------------------------------------------------------------------------
@@ -155,7 +171,7 @@ sourceFromIndices value n = S.take value $ S.fromIndices (+ n)
156{-# INLINE sourceFromIndicesM #-}
172{-# INLINE sourceFromIndicesM #-}
157sourceFromIndicesM :: (S.MonadAsync m, S.IsStream t) => Int -> Int -> t m Int
173sourceFromIndicesM :: (S.MonadAsync m, S.IsStream t) => Int -> Int -> t m Int
158−sourceFromIndicesM value n = S.take value $ S.fromIndicesM (Prelude.fmap return (+ n))
174+sourceFromIndicesM value n = S.take value $ S.fromIndicesM (P.fmap return (+ n))
160-- fromList
176-- fromList
@@ -165,7 +181,7 @@ sourceFromList value n = S.fromList [n..n+value]
166{-# INLINE sourceFromListM #-}
182{-# INLINE sourceFromListM #-}
167sourceFromListM :: (S.MonadAsync m, S.IsStream t) => Int -> Int -> t m Int
183sourceFromListM :: (S.MonadAsync m, S.IsStream t) => Int -> Int -> t m Int
168−sourceFromListM value n = S.fromListM (Prelude.fmap return [n..n+value])
184+sourceFromListM value n = S.fromListM (P.fmap return [n..n+value])
170{-# INLINE sourceIsList #-}
186{-# INLINE sourceIsList #-}
171sourceIsList :: Int -> Int -> S.SerialT Identity Int
187sourceIsList :: Int -> Int -> S.SerialT Identity Int
@@ -183,7 +199,7 @@ sourceFromFoldable value n = S.fromFoldable [n..n+value]
184{-# INLINE sourceFromFoldableM #-}
200{-# INLINE sourceFromFoldableM #-}
185sourceFromFoldableM :: (S.IsStream t, S.MonadAsync m) => Int -> Int -> t m Int
201sourceFromFoldableM :: (S.IsStream t, S.MonadAsync m) => Int -> Int -> t m Int
186−sourceFromFoldableM value n = S.fromFoldableM (Prelude.fmap return [n..n+value])
202+sourceFromFoldableM value n = S.fromFoldableM (P.fmap return [n..n+value])
188{-# INLINE currentTime #-}
204{-# INLINE currentTime #-}
189currentTime :: (S.IsStream t, S.MonadAsync m)
205currentTime :: (S.IsStream t, S.MonadAsync m)
@@ -262,11 +278,11 @@ uncons s = do
263{-# INLINE init #-}
279{-# INLINE init #-}
264init :: Monad m => Stream m a -> m ()
280init :: Monad m => Stream m a -> m ()
265−init s = S.init s >>= Prelude.mapM_ S.drain
281+init s = S.init s >>= P.mapM_ S.drain
267{-# INLINE tail #-}
283{-# INLINE tail #-}
268tail :: Monad m => Stream m a -> m ()
284tail :: Monad m => Stream m a -> m ()
269−tail s = S.tail s >>= Prelude.mapM_ tail
285+tail s = S.tail s >>= P.mapM_ tail
271{-# INLINE nullHeadTail #-}
287{-# INLINE nullHeadTail #-}
272nullHeadTail :: Monad m => Stream m Int -> m ()
288nullHeadTail :: Monad m => Stream m Int -> m ()
@@ -274,7 +290,7 @@ nullHeadTail s = do
274 r <- S.null s
290 r <- S.null s
275 when (not r) $ do
291 when (not r) $ do
276 _ <- S.head s
292 _ <- S.head s
277− S.tail s >>= Prelude.mapM_ nullHeadTail
293+ S.tail s >>= P.mapM_ nullHeadTail
279{-# INLINE mapM_ #-}
295{-# INLINE mapM_ #-}
280mapM_ :: Monad m => Stream m Int -> m ()
296mapM_ :: Monad m => Stream m Int -> m ()
@@ -419,8 +435,8 @@ sequence :: (S.IsStream t, S.MonadAsync m)
420scan n = composeN n $ S.scanl' (+) 0
436scan n = composeN n $ S.scanl' (+) 0
421scanl1' n = composeN n $ S.scanl1' (+)
437scanl1' n = composeN n $ S.scanl1' (+)
422−fmap n = composeN n $ Prelude.fmap (+1)
438+fmap n = composeN n $ P.fmap (+1)
423−fmap' t n = composeN' n $ t . Prelude.fmap (+1)
439+fmap' t n = composeN' n $ t . P.fmap (+1)
424map n = composeN n $ S.map (+1)
440map n = composeN n $ S.map (+1)
425map' t n = composeN' n $ t . S.map (+1)
441map' t n = composeN' n $ t . S.map (+1)
426mapM t n = composeN' n $ t . S.mapM return
442mapM t n = composeN' n $ t . S.mapM return
@@ -450,9 +466,9 @@ tapAsync :: S.MonadAsync m => Int -> Stream m Int -> m ()
450tapAsync n = composeN n $ Internal.tapAsync FL.sum
466tapAsync n = composeN n $ Internal.tapAsync FL.sum
452mapMaybe n = composeN n $ S.mapMaybe
468mapMaybe n = composeN n $ S.mapMaybe
453− (\x -> if Prelude.odd x then Nothing else Just x)
469+ (\x -> if P.odd x then Nothing else Just x)
454mapMaybeM n = composeN n $ S.mapMaybeM
470mapMaybeM n = composeN n $ S.mapMaybeM
455− (\x -> if Prelude.odd x then return Nothing else return $ Just x)
471+ (\x -> if P.odd x then return Nothing else return $ Just x)
456sequence t = transform . t . S.sequence
472sequence t = transform . t . S.sequence
457filterEven n = composeN n $ S.filter even
473filterEven n = composeN n $ S.filter even
458filterAllOut value n = composeN n $ S.filter (> (value + 1))
474filterAllOut value n = composeN n $ S.filter (> (value + 1))
@@ -1221,3 +1237,762 @@ traversableMapM = P.mapM return
1221{-# INLINE traversableSequence #-}
1237{-# INLINE traversableSequence #-}
1222traversableSequence :: Stream Identity Int -> IO (Stream Identity Int)
1238traversableSequence :: Stream Identity Int -> IO (Stream Identity Int)
1223traversableSequence = P.sequence . P.fmap return
1239traversableSequence = P.sequence . P.fmap return
1241+-------------------------------------------------------------------------------
1243+-------------------------------------------------------------------------------
1245+-- We need a monadic bind here to make sure that the function f does not get
1246+-- completely optimized out by the compiler in some cases.
1248+-- | Takes a fold method, and uses it with a default source.
1249+{-# INLINE benchIOSink #-}
1251+ :: (IsStream t, NFData b)
1252+ => Int -> String -> (t IO Int -> IO b) -> Benchmark
1253+benchIOSink value name f = bench name $ nfIO $ randomRIO (1,1) >>= f . source value
1255+{-# INLINE benchHoistSink #-}
1257+ :: (IsStream t, NFData b)
1258+ => Int -> String -> (t Identity Int -> IO b) -> Benchmark
1259+benchHoistSink value name f =
1260+ bench name $ nfIO $ randomRIO (1,1) >>= f . sourceUnfoldr value
1262+-- XXX We should be using sourceUnfoldrM for fair comparison with IO monad, but
1263+-- we can't use it as it requires MonadAsync constraint.
1264+{-# INLINE benchIdentitySink #-}
1266+ :: (IsStream t, NFData b)
1267+ => Int -> String -> (t Identity Int -> Identity b) -> Benchmark
1268+benchIdentitySink value name f = bench name $ nf (f . sourceUnfoldr value) 1
1270+-- | Takes a source, and uses it with a default drain/fold method.
1271+{-# INLINE benchIOSrc #-}
1273+ :: (t IO a -> SerialT IO a)
1277+benchIOSrc t name f =
1278+ bench name $ nfIO $ randomRIO (1,1) >>= toNull t . f
1280+{-# INLINE benchPureSink #-}
1281+benchPureSink :: NFData b => Int -> String -> (SerialT Identity Int -> b) -> Benchmark
1282+benchPureSink value name f = benchPure name (sourceUnfoldr value) f
1284+benchIO :: (NFData b) => String -> (Int -> IO b) -> Benchmark
1285+benchIO name f = bench name $ nfIO $ randomRIO (1,1) >>= f
1287+-------------------------------------------------------------------------------
1288+-- Serial : O(1) Space
1289+-------------------------------------------------------------------------------
1291+o_1_space_serial_pure :: Int -> [Benchmark]
1292+o_1_space_serial_pure value =
1297+ [ benchPureSink value "id" P.id
1298+ , benchPureSink1 "eqBy" (eqByPure value)
1299+ , benchPureSink value "==" eqInstance
1300+ , benchPureSink value "/=" eqInstanceNotEq
1301+ , benchPureSink1 "cmpBy" (cmpByPure value)
1302+ , benchPureSink value "<" ordInstance
1303+ , benchPureSink value "min" ordInstanceMin
1304+ , benchPureSrc "IsList.fromList" (sourceIsList value)
1305+ -- length is used to check for foldr/build fusion
1308+ "length . IsList.toList"
1309+ (P.length . GHC.toList)
1310+ , benchPureSrc "IsString.fromString" (sourceIsString value)
1311+ , benchPureSink value "showsPrec pure streams" showInstance
1312+ , benchPureSink value "foldl'" pureFoldl'
1317+o_1_space_serial_foldable :: Int -> [Benchmark]
1318+o_1_space_serial_foldable value =
1323+ -- Foldable instance
1324+ -- type class operations
1325+ [ bench "foldl'" $ nf (foldableFoldl' value) 1
1326+ , bench "foldrElem" $ nf (foldableFoldrElem value) 1
1327+ -- , bench "null" $ nf (foldableNull value) 1
1328+ , bench "elem" $ nf (foldableElem value) 1
1329+ , bench "length" $ nf (foldableLength value) 1
1330+ , bench "sum" $ nf (foldableSum value) 1
1331+ , bench "product" $ nf (foldableProduct value) 1
1332+ , bench "minimum" $ nf (foldableMin value) 1
1333+ , bench "maximum" $ nf (foldableMax value) 1
1334+ , bench "length . toList" $
1335+ nf (P.length . foldableToList value) 1
1337+ , bench "notElem" $ nf (foldableNotElem value) 1
1338+ , bench "find" $ nf (foldableFind value) 1
1339+ , bench "all" $ nf (foldableAll value) 1
1340+ , bench "any" $ nf (foldableAny value) 1
1341+ , bench "and" $ nf (foldableAnd value) 1
1342+ , bench "or" $ nf (foldableOr value) 1
1343+ -- Note: minimumBy/maximumBy do not work in constant memory they are in
1344+ -- the O(n) group of benchmarks down below in this file.
1345+ -- Applicative and Traversable operations
1347+ , benchIOSink1 "mapM_" (foldableMapM_ value)
1350+ , benchIOSink1 "sequence_" (foldableSequence_ value)
1353+ -- , benchIOSink1 "msum" (foldableMsum value)
1358+o_1_space_serial_generation :: Int -> [Benchmark]
1359+o_1_space_serial_generation value =
1364+ -- Most basic, barely stream continuations running
1365+ [ benchIOSrc serially "unfoldr" (sourceUnfoldr value)
1366+ , benchIOSrc serially "unfoldrM" (sourceUnfoldrM value)
1367+ , benchIOSrc serially "intFromTo" (sourceIntFromTo value)
1371+ (sourceIntFromThenTo value)
1375+ (sourceIntegerFromStep value)
1379+ (sourceFracFromThenTo value)
1380+ , benchIOSrc serially "fracFromTo" (sourceFracFromTo value)
1381+ , benchIOSrc serially "fromList" (sourceFromList value)
1382+ , benchIOSrc serially "fromListM" (sourceFromListM value)
1383+ -- These are essentially cons and consM
1387+ (sourceFromFoldable value)
1391+ (sourceFromFoldableM value)
1392+ , benchIOSrc serially "currentTime/0.00001s" $
1393+ currentTime value 0.00001
1398+o_1_space_serial_elimination :: Int -> [Benchmark]
1399+o_1_space_serial_elimination value =
1408+ [ benchIOSink value "foldl'" foldl'Reduce
1409+ , benchIOSink value "foldl1'" foldl1'Reduce
1410+ , benchIOSink value "foldlM'" foldlM'Reduce
1414+ [ benchIdentitySink value "foldl'" foldl'Reduce
1415+ , benchIdentitySink
1419+ , benchIdentitySink
1436+ [ benchIdentitySink
1440+ , benchIdentitySink
1442+ "foldrMToStreamLength"
1443+ (S.length . runIdentity . foldrMToStream)
1446+ "foldrMToListLength"
1447+ (P.length . runIdentity . foldrMBuild)
1450+ , benchIOSink value "uncons" uncons
1451+ , benchIOSink value "toNull" $ toNull serially
1452+ , benchIOSink value "mapM_" mapM_
1453+ , benchIOSink value "init" init
1454+ -- this is too low and causes all benchmarks reported in ns
1455+ -- , benchIOSink value "head" head
1456+ , benchIOSink value "last" last
1457+ -- , benchIOSink value "lookup" lookup
1458+ , benchIOSink value "find" (find value)
1459+ , benchIOSink value "findIndex" (findIndex value)
1460+ , benchIOSink value "elemIndex" (elemIndex value)
1461+ -- this is too low and causes all benchmarks reported in ns
1462+ -- , benchIOSink value "null" null
1463+ , benchIOSink value "elem" (elem value)
1464+ , benchIOSink value "notElem" (notElem value)
1465+ , benchIOSink value "all" (all value)
1466+ , benchIOSink value "any" (any value)
1467+ , benchIOSink value "and" (and value)
1468+ , benchIOSink value "or" (or value)
1469+ , benchIOSink value "length" length
1472+ "length . generally"
1473+ (length . IP.generally)
1474+ , benchIOSink value "sum" sum
1475+ , benchIOSink value "product" product
1476+ , benchIOSink value "maximumBy" maximumBy
1477+ , benchIOSink value "maximum" maximum
1478+ , benchIOSink value "minimumBy" minimumBy
1479+ , benchIOSink value "minimum" minimum
1484+o_1_space_serial_folds :: Int -> [Benchmark]
1485+o_1_space_serial_folds value =
1490+ [ benchIOSink value "drain" (S.fold FL.drain)
1491+ , benchIOSink value "drainN" (S.fold (IFL.drainN value))
1495+ (S.fold (IFL.drainWhile $ (<=) (value + 1)))
1499+ (S.fold (IFL.drainWhile $ (>=) (value + 1)))
1500+ , benchIOSink value "sink" (S.fold $ Sink.toFold Sink.drain)
1501+ , benchIOSink value "last" (S.fold FL.last)
1502+ , benchIOSink value "lastN.1" (S.fold (IA.lastN 1))
1503+ , benchIOSink value "lastN.10" (S.fold (IA.lastN 10))
1504+ , benchIOSink value "length" (S.fold FL.length)
1505+ , benchIOSink value "sum" (S.fold FL.sum)
1506+ , benchIOSink value "product" (S.fold FL.product)
1507+ , benchIOSink value "maximumBy" (S.fold (FL.maximumBy compare))
1508+ , benchIOSink value "maximum" (S.fold FL.maximum)
1509+ , benchIOSink value "minimumBy" (S.fold (FL.minimumBy compare))
1510+ , benchIOSink value "minimum" (S.fold FL.minimum)
1517+ (S.map (fromIntegral :: Int -> Double) s))
1524+ (S.map (fromIntegral :: Int -> Double) s))
1531+ (S.map (fromIntegral :: Int -> Double) s))
1535+ (S.fold FL.mconcat . (S.map (Last . Just)))
1539+ (S.fold (FL.foldMap (Last . Just)))
1540+ , benchIOSink value "index" (S.fold (FL.index (value + 1)))
1541+ , benchIOSink value "head" (S.fold FL.head)
1542+ , benchIOSink value "find" (S.fold (FL.find (== (value + 1))))
1546+ (S.fold (FL.findIndex (== (value + 1))))
1550+ (S.fold (FL.elemIndex (value + 1)))
1551+ , benchIOSink value "null" (S.fold FL.null)
1552+ , benchIOSink value "elem" (S.fold (FL.elem (value + 1)))
1553+ , benchIOSink value "notElem" (S.fold (FL.notElem (value + 1)))
1554+ , benchIOSink value "all" (S.fold (FL.all (<= (value + 1))))
1555+ , benchIOSink value "any" (S.fold (FL.any (> (value + 1))))
1559+ (\s -> S.fold FL.and (S.map (<= (value + 1)) s))
1563+ (\s -> S.fold FL.or (S.map (> (value + 1)) s))
1568+o_1_space_serial_foldMultiStream :: Int -> [Benchmark]
1569+o_1_space_serial_foldMultiStream value =
1573+ "fold-multi-stream"
1574+ [ benchIOSink1 "eqBy" (eqBy value)
1575+ , benchIOSink1 "cmpBy" (cmpBy value)
1576+ , benchIOSink value "isPrefixOf" isPrefixOf
1577+ , benchIOSink value "isSubsequenceOf" isSubsequenceOf
1578+ , benchIOSink value "stripPrefix" stripPrefix
1583+o_1_space_serial_foldsTransforms :: Int -> [Benchmark]
1584+o_1_space_serial_foldsTransforms value =
1589+ [ benchIOSink value "drain" (S.fold FL.drain)
1590+ , benchIOSink value "lmap" (S.fold (IFL.lmap (+ 1) FL.drain))
1596+ (Pipe.mapM (\x -> return $ x + 1))
1602+o_1_space_serial_foldsCompositions :: Int -> [Benchmark]
1603+o_1_space_serial_foldsCompositions value =
1607+ "folds-compositions" -- Applicative
1612+ ((,) <$> FL.all (<= (value + 1)) <*>
1613+ FL.any (> (value + 1))))
1617+ (S.fold ((,) <$> FL.sum <*> FL.length))
1622+o_1_space_serial_pipes :: Int -> [Benchmark]
1623+o_1_space_serial_pipes value =
1628+ [ benchIOSink value "mapM" (transformMapM serially 1)
1632+ (transformComposeMapM serially 1)
1633+ , benchIOSink value "tee" (transformTeeMapM serially 1)
1634+ , benchIOSink value "zip" (transformZipMapM serially 1)
1639+o_1_space_serial_pipesX4 :: Int -> [Benchmark]
1640+o_1_space_serial_pipesX4 value =
1645+ [ benchIOSink value "mapM" (transformMapM serially 4)
1649+ (transformComposeMapM serially 4)
1650+ , benchIOSink value "tee" (transformTeeMapM serially 4)
1651+ , benchIOSink value "zip" (transformZipMapM serially 4)
1657+o_1_space_serial_transformer :: Int -> [Benchmark]
1658+o_1_space_serial_transformer value =
1663+ [ benchIOSrc serially "evalState" (evalStateT value)
1664+ , benchIOSrc serially "withState" (withState value)
1669+o_1_space_serial_transformation :: Int -> [Benchmark]
1670+o_1_space_serial_transformation value =
1675+ [ benchIOSink value "scanl" (scan 1)
1676+ , benchIOSink value "scanl1'" (scanl1' 1)
1677+ , benchIOSink value "map" (map 1)
1678+ , benchIOSink value "fmap" (fmap 1)
1679+ , benchIOSink value "mapM" (mapM serially 1)
1680+ , benchIOSink value "mapMaybe" (mapMaybe 1)
1681+ , benchIOSink value "mapMaybeM" (mapMaybeM 1)
1682+ , bench "sequence" $
1684+ randomRIO (1, 1000) >>= \n ->
1685+ sequence serially (sourceUnfoldrMAction value n)
1686+ , benchIOSink value "findIndices" (findIndices value 1)
1687+ , benchIOSink value "elemIndices" (elemIndices value 1)
1688+ , benchIOSink value "foldrS" (foldrS 1)
1689+ , benchIOSink value "foldrSMap" (foldrSMap 1)
1690+ , benchIOSink value "foldrT" (foldrT 1)
1691+ , benchIOSink value "foldrTMap" (foldrTMap 1)
1692+ , benchIOSink value "tap" (tap 1)
1693+ , benchIOSink value "tapRate 1 second" (tapRate 1)
1694+ , benchIOSink value "pollCounts 1 second" (pollCounts 1)
1695+ , benchIOSink value "tapAsync" (tapAsync 1)
1696+ , benchIOSink value "tapAsyncS" (tapAsyncS 1)
1701+o_1_space_serial_transformationX4 :: Int -> [Benchmark]
1702+o_1_space_serial_transformationX4 value =
1707+ [ benchIOSink value "scan" (scan 4)
1708+ , benchIOSink value "scanl1'" (scanl1' 4)
1709+ , benchIOSink value "map" (map 4)
1710+ , benchIOSink value "fmap" (fmap 4)
1711+ , benchIOSink value "mapM" (mapM serially 4)
1712+ , benchIOSink value "mapMaybe" (mapMaybe 4)
1713+ , benchIOSink value "mapMaybeM" (mapMaybeM 4)
1714+ -- , bench "sequence" $ nfIO $ randomRIO (1,1000) >>= \n ->
1715+ -- sequence serially (sourceUnfoldrMAction n)
1716+ , benchIOSink value "findIndices" (findIndices value 4)
1717+ , benchIOSink value "elemIndices" (elemIndices value 4)
1722+o_1_space_serial_filtering :: Int -> [Benchmark]
1723+o_1_space_serial_filtering value =
1728+ [ benchIOSink value "filter-even" (filterEven 1)
1729+ , benchIOSink value "filter-all-out" (filterAllOut value 1)
1730+ , benchIOSink value "filter-all-in" (filterAllIn value 1)
1731+ , benchIOSink value "take-all" (takeAll value 1)
1735+ (takeByTime (NanoSecond64 maxBound) 1)
1736+ , benchIOSink value "takeWhile-true" (takeWhileTrue value 1)
1737+ --, benchIOSink value "takeWhileM-true" (takeWhileMTrue 1)
1738+ -- "drop-one" is dual to "last"
1739+ , benchIOSink value "drop-one" (dropOne 1)
1740+ , benchIOSink value "drop-all" (dropAll value 1)
1744+ (dropByTime (NanoSecond64 maxBound) 1)
1745+ , benchIOSink value "dropWhile-true" (dropWhileTrue value 1)
1746+ --, benchIOSink value "dropWhileM-true" (dropWhileMTrue 1)
1750+ (dropWhileFalse value 1)
1751+ , benchIOSink value "deleteBy" (deleteBy value 1)
1752+ , benchIOSink value "intersperse" (intersperse value 1)
1753+ , benchIOSink value "insertBy" (insertBy value 1)
1758+o_1_space_serial_filteringX4 :: Int -> [Benchmark]
1759+o_1_space_serial_filteringX4 value =
1764+ [ benchIOSink value "filter-even" (filterEven 4)
1765+ , benchIOSink value "filter-all-out" (filterAllOut value 4)
1766+ , benchIOSink value "filter-all-in" (filterAllIn value 4)
1767+ , benchIOSink value "take-all" (takeAll value 4)
1768+ , benchIOSink value "takeWhile-true" (takeWhileTrue value 4)
1769+ --, benchIOSink value "takeWhileM-true" (takeWhileMTrue 4)
1770+ , benchIOSink value "drop-one" (dropOne 4)
1771+ , benchIOSink value "drop-all" (dropAll value 4)
1772+ , benchIOSink value "dropWhile-true" (dropWhileTrue value 4)
1773+ --, benchIOSink value "dropWhileM-true" (dropWhileMTrue 4)
1777+ (dropWhileFalse value 4)
1778+ , benchIOSink value "deleteBy" (deleteBy value 4)
1779+ , benchIOSink value "intersperse" (intersperse value 4)
1780+ , benchIOSink value "insertBy" (insertBy value 4)
1786+o_1_space_serial_joining :: Int -> [Benchmark]
1787+o_1_space_serial_joining value =
1792+ [ benchIOSrc1 "zip (2,x/2)" (zip (value `div` 2))
1793+ , benchIOSrc1 "zipM (2,x/2)" (zipM (value `div` 2))
1794+ , benchIOSrc1 "mergeBy (2,x/2)" (mergeBy (value `div` 2))
1795+ , benchIOSrc1 "serial (2,x/2)" (serial2 (value `div` 2))
1796+ , benchIOSrc1 "append (2,x/2)" (append2 (value `div` 2))
1797+ , benchIOSrc1 "serial (2,2,x/4)" (serial4 (value `div` 4))
1798+ , benchIOSrc1 "append (2,2,x/4)" (append4 (value `div` 4))
1799+ , benchIOSrc1 "wSerial (2,x/2)" (wSerial2 value) -- XXX Move this elsewhere?
1800+ , benchIOSrc1 "interleave (2,x/2)" (interleave2 value)
1801+ , benchIOSrc1 "roundRobin (2,x/2)" (roundRobin2 value)
1807+o_1_space_serial_concatFoldable :: Int -> [Benchmark]
1808+o_1_space_serial_concatFoldable value =
1816+ (sourceFoldMapWith value)
1820+ (sourceFoldMapWithM value)
1821+ , benchIOSrc serially "foldMapM" (sourceFoldMapM value)
1824+ "foldWithConcatMapId"
1825+ (sourceConcatMapId value)
1830+o_1_space_serial_concatSerial :: Int -> [Benchmark]
1831+o_1_space_serial_concatSerial value =
1837+ "concatMapPure (2,x/2)"
1838+ (concatMapPure 2 (value `div` 2))
1840+ "concatMap (2,x/2)"
1841+ (concatMap 2 (value `div` 2))
1843+ "concatMap (x/2,2)"
1844+ (concatMap (value `div` 2) 2)
1846+ "concatMapRepl (x/4,4)"
1847+ (concatMapRepl4xN value)
1849+ "concatUnfoldRepl (x/4,4)"
1850+ (concatUnfoldRepl4xN value)
1852+ "concatMapWithSerial (2,x/2)"
1853+ (concatMapWithSerial 2 (value `div` 2))
1855+ "concatMapWithSerial (x/2,2)"
1856+ (concatMapWithSerial (value `div` 2) 2)
1858+ "concatMapWithAppend (2,x/2)"
1859+ (concatMapWithAppend 2 (value `div` 2))
1865+o_1_space_serial_outerProductStreams :: Int -> [Benchmark]
1866+o_1_space_serial_outerProductStreams value =
1870+ "outer-product-streams"
1871+ [ benchIO "toNullAp" $ Nested.toNullAp value serially
1872+ , benchIO "toNull" $ Nested.toNull value serially
1873+ , benchIO "toNull3" $ Nested.toNull3 value serially
1874+ , benchIO "filterAllOut" $ Nested.filterAllOut value serially
1875+ , benchIO "filterAllIn" $ Nested.filterAllIn value serially
1876+ , benchIO "filterSome" $ Nested.filterSome value serially
1877+ , benchIO "breakAfterSome" $
1878+ Nested.breakAfterSome value serially
1884+o_1_space_serial_outerProductUnfolds :: Int -> [Benchmark]
1885+o_1_space_serial_outerProductUnfolds value =
1889+ "outer-product-unfolds"
1890+ [ benchIO "toNull" $ NestedUnfold.toNull value
1891+ , benchIO "toNull3" $ NestedUnfold.toNull3 value
1892+ , benchIO "concat" $ NestedUnfold.concat value
1893+ , benchIO "filterAllOut" $ NestedUnfold.filterAllOut value
1894+ , benchIO "filterAllIn" $ NestedUnfold.filterAllIn value
1895+ , benchIO "filterSome" $ NestedUnfold.filterSome value
1896+ , benchIO "breakAfterSome" $ NestedUnfold.breakAfterSome value
1902+o_1_space_serial_mixed :: Int -> [Benchmark]
1903+o_1_space_serial_mixed value =
1906+ -- scanl-map and foldl-map are equivalent to the scan and fold in the foldl
1907+ -- library. If scan/fold followed by a map is efficient enough we may not
1908+ -- need monolithic implementations of these.
1911+ [ benchIOSink value "scanl-map" (scanMap 1)
1912+ , benchIOSink value "foldl-map" foldl'ReduceMap
1913+ , benchIOSink value "sum-product-fold" sumProductFold
1914+ , benchIOSink value "sum-product-scan" sumProductScan
1919+o_1_space_serial_mixedX4 :: Int -> [Benchmark]
1920+o_1_space_serial_mixedX4 value =
1925+ [ benchIOSink value "scan-map" (scanMap 4)
1926+ , benchIOSink value "drop-map" (dropMap 4)
1927+ , benchIOSink value "drop-scan" (dropScan 4)
1928+ , benchIOSink value "take-drop" (takeDrop value 4)
1929+ , benchIOSink value "take-scan" (takeScan value 4)
1930+ , benchIOSink value "take-map" (takeMap value 4)
1931+ , benchIOSink value "filter-drop" (filterDrop value 4)
1932+ , benchIOSink value "filter-take" (filterTake value 4)
1933+ , benchIOSink value "filter-scan" (filterScan 4)
1934+ , benchIOSink value "filter-scanl1" (filterScanl1 4)
1935+ , benchIOSink value "filter-map" (filterMap value 4)
1940+o_1_space_wSerial_transformation :: Int -> [Benchmark]
1941+o_1_space_wSerial_transformation value =
1946+ [benchIOSink value "fmap" $ fmap' wSerially 1]
1950+o_1_space_wSerial_concatMap :: Int -> [Benchmark]
1951+o_1_space_wSerial_concatMap value =
1957+ "concatMapWithWSerial (2,x/2)"
1958+ (concatMapWithWSerial 2 (value `div` 2))
1960+ "concatMapWithWSerial (x/2,2)"
1961+ (concatMapWithWSerial (value `div` 2) 2)
1966+o_1_space_wSerial_outerProduct :: Int -> [Benchmark]
1967+o_1_space_wSerial_outerProduct value =
1972+ [ benchIO "toNullAp" $ Nested.toNullAp value wSerially
1973+ , benchIO "toNull" $ Nested.toNull value wSerially
1974+ , benchIO "toNull3" $ Nested.toNull3 value wSerially
1975+ , benchIO "filterAllOut" $ Nested.filterAllOut value wSerially
1976+ , benchIO "filterAllIn" $ Nested.filterAllIn value wSerially
1977+ , benchIO "filterSome" $ Nested.filterSome value wSerially
1978+ , benchIO "breakAfterSome" $
1979+ Nested.breakAfterSome value wSerially
1984+o_1_space_zipSerial_transformation :: Int -> [Benchmark]
1985+o_1_space_zipSerial_transformation value =
1990+ [benchIOSink value "fmap" $ fmap' zipSerially 1]
1991+ -- XXX needs fixing
1993+ , bgroup "outer-product"
1994+ [ benchIO "toNullAp" $ Nested.toNullAp value zipSerially