@@ -23,16 +23,18 @@
2323
2424module Streamly.Benchmark.Prelude where
2525
26−import Control.DeepSeq (NFData)
26+import Control.DeepSeq (NFData(..))
2727import Control.Monad (when)
2828import Control.Monad.IO.Class (MonadIO(..))
2929import Control.Monad.State.Strict (StateT, get, put)
3030import Data.Functor.Identity (Identity, runIdentity)
3131import Data.IORef (newIORef, modifyIORef')
32+import Data.Monoid (Last(..))
3233import GHC.Generics (Generic)
34+import System.Random (randomRIO)
3335import Prelude
34− (Monad, Int, (+), ($), (.), return, fmap, even, (>), (<=), (==), (>=),
35− subtract, undefined, Maybe(..), odd, Bool, not, (>>=), mapM_, curry,
36+ (Monad, String, Int, (+), ($), (.), return, even, (>), (<=), (==), (>=),
37+ subtract, undefined, Maybe(..), Bool, not, (>>=), curry,
3638 maxBound, div, IO, compare, Double, fromIntegral, Integer, (<$>),
3739 (<*>), flip)
3840import qualified Prelude as P
@@ -46,6 +48,7 @@ import Test.Inspection
4648import qualified Streamly.Internal.Data.Stream.StreamD as D
4749#endif
4850
51+import Streamly (SerialT, IsStream, wSerially, zipSerially, serially)
4952import qualified Streamly as S hiding (runStream)
5053import qualified Streamly.Prelude as S
5154import qualified Streamly.Internal.Prelude as Internal
@@ -55,6 +58,19 @@ import qualified Streamly.Internal.Data.Pipe as Pipe
5558import qualified Streamly.Internal.Data.Stream.Parallel as Par
5659import Streamly.Internal.Data.Time.Units
5760
61+import qualified Streamly.Internal.Data.Sink as Sink
62+
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
66+
67+import qualified NestedOps as Nested
68+import qualified NestedUnfoldOps as NestedUnfold
69+
70+import Gauge
71+import Streamly.Benchmark.Common
72+
73+
5874type Stream m a = S.SerialT m a
5975
6076-------------------------------------------------------------------------------
@@ -155,7 +171,7 @@ sourceFromIndices value n = S.take value $ S.fromIndices (+ n)
155171
156172{-# INLINE sourceFromIndicesM #-}
157173sourceFromIndicesM :: (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))
159175
160176-- fromList
161177
@@ -165,7 +181,7 @@ sourceFromList value n = S.fromList [n..n+value]
165181
166182{-# INLINE sourceFromListM #-}
167183sourceFromListM :: (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])
169185
170186{-# INLINE sourceIsList #-}
171187sourceIsList :: Int -> Int -> S.SerialT Identity Int
@@ -183,7 +199,7 @@ sourceFromFoldable value n = S.fromFoldable [n..n+value]
183199
184200{-# INLINE sourceFromFoldableM #-}
185201sourceFromFoldableM :: (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])
187203
188204{-# INLINE currentTime #-}
189205currentTime :: (S.IsStream t, S.MonadAsync m)
@@ -262,11 +278,11 @@ uncons s = do
262278
263279{-# INLINE init #-}
264280init :: 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
266282
267283{-# INLINE tail #-}
268284tail :: Monad m => Stream m a -> m ()
269−tail s = S.tail s >>= Prelude.mapM_ tail
285+tail s = S.tail s >>= P.mapM_ tail
270286
271287{-# INLINE nullHeadTail #-}
272288nullHeadTail :: Monad m => Stream m Int -> m ()
@@ -274,7 +290,7 @@ nullHeadTail s = do
274290 r <- S.null s
275291 when (not r) $ do
276292 _ <- S.head s
277− S.tail s >>= Prelude.mapM_ nullHeadTail
293+ S.tail s >>= P.mapM_ nullHeadTail
278294
279295{-# INLINE mapM_ #-}
280296mapM_ :: Monad m => Stream m Int -> m ()
@@ -419,8 +435,8 @@ sequence :: (S.IsStream t, S.MonadAsync m)
419435
420436scan n = composeN n $ S.scanl' (+) 0
421437scanl1' n = composeN n $ S.scanl1' (+)
422−fmap n = composeN n $ Prelude.fmap (+1)
423−fmap' t n = composeN' n $ t . Prelude.fmap (+1)
438+fmap n = composeN n $ P.fmap (+1)
439+fmap' t n = composeN' n $ t . P.fmap (+1)
424440map n = composeN n $ S.map (+1)
425441map' t n = composeN' n $ t . S.map (+1)
426442mapM t n = composeN' n $ t . S.mapM return
@@ -450,9 +466,9 @@ tapAsync :: S.MonadAsync m => Int -> Stream m Int -> m ()
450466tapAsync n = composeN n $ Internal.tapAsync FL.sum
451467
452468mapMaybe 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)
454470mapMaybeM 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)
456472sequence t = transform . t . S.sequence
457473filterEven n = composeN n $ S.filter even
458474filterAllOut value n = composeN n $ S.filter (> (value + 1))
@@ -1221,3 +1237,762 @@ traversableMapM = P.mapM return
12211237{-# INLINE traversableSequence #-}
12221238traversableSequence :: Stream Identity Int -> IO (Stream Identity Int)
12231239traversableSequence = P.sequence . P.fmap return
1240+
1241+-------------------------------------------------------------------------------
1242+-- Benchmark groups
1243+-------------------------------------------------------------------------------
1244+
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.
1247+
1248+-- | Takes a fold method, and uses it with a default source.
1249+{-# INLINE benchIOSink #-}
1250+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
1254+
1255+{-# INLINE benchHoistSink #-}
1256+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
1261+
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 #-}
1265+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
1269+
1270+-- | Takes a source, and uses it with a default drain/fold method.
1271+{-# INLINE benchIOSrc #-}
1272+benchIOSrc
1273+ :: (t IO a -> SerialT IO a)
1274+ -> String
1275+ -> (Int -> t IO a)
1276+ -> Benchmark
1277+benchIOSrc t name f =
1278+ bench name $ nfIO $ randomRIO (1,1) >>= toNull t . f
1279+
1280+{-# INLINE benchPureSink #-}
1281+benchPureSink :: NFData b => Int -> String -> (SerialT Identity Int -> b) -> Benchmark
1282+benchPureSink value name f = benchPure name (sourceUnfoldr value) f
1283+
1284+benchIO :: (NFData b) => String -> (Int -> IO b) -> Benchmark
1285+benchIO name f = bench name $ nfIO $ randomRIO (1,1) >>= f
1286+
1287+-------------------------------------------------------------------------------
1288+-- Serial : O(1) Space
1289+-------------------------------------------------------------------------------
1290+
1291+o_1_space_serial_pure :: Int -> [Benchmark]
1292+o_1_space_serial_pure value =
1293+ [ bgroup
1294+ "serially"
1295+ [ bgroup
1296+ "pure"
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
1306+ , benchPureSink
1307+ value
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'
1313+ ]
1314+ ]
1315+ ]
1316+
1317+o_1_space_serial_foldable :: Int -> [Benchmark]
1318+o_1_space_serial_foldable value =
1319+ [ bgroup
1320+ "serially"
1321+ [ bgroup
1322+ "foldable"
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
1336+ -- folds
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
1346+ -- TBD: traverse_
1347+ , benchIOSink1 "mapM_" (foldableMapM_ value)
1348+ -- TBD: for_
1349+ -- TBD: forM_
1350+ , benchIOSink1 "sequence_" (foldableSequence_ value)
1351+ -- TBD: sequenceA_
1352+ -- TBD: asum
1353+ -- , benchIOSink1 "msum" (foldableMsum value)
1354+ ]
1355+ ]
1356+ ]
1357+
1358+o_1_space_serial_generation :: Int -> [Benchmark]
1359+o_1_space_serial_generation value =
1360+ [ bgroup
1361+ "serially"
1362+ [ bgroup
1363+ "generation"
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)
1368+ , benchIOSrc
1369+ serially
1370+ "intFromThenTo"
1371+ (sourceIntFromThenTo value)
1372+ , benchIOSrc
1373+ serially
1374+ "integerFromStep"
1375+ (sourceIntegerFromStep value)
1376+ , benchIOSrc
1377+ serially
1378+ "fracFromThenTo"
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
1384+ , benchIOSrc
1385+ serially
1386+ "fromFoldable"
1387+ (sourceFromFoldable value)
1388+ , benchIOSrc
1389+ serially
1390+ "fromFoldableM"
1391+ (sourceFromFoldableM value)
1392+ , benchIOSrc serially "currentTime/0.00001s" $
1393+ currentTime value 0.00001
1394+ ]
1395+ ]
1396+ ]
1397+
1398+o_1_space_serial_elimination :: Int -> [Benchmark]
1399+o_1_space_serial_elimination value =
1400+ [ bgroup
1401+ "serially"
1402+ [ bgroup
1403+ "elimination"
1404+ [ bgroup
1405+ "reduce"
1406+ [ bgroup
1407+ "IO"
1408+ [ benchIOSink value "foldl'" foldl'Reduce
1409+ , benchIOSink value "foldl1'" foldl1'Reduce
1410+ , benchIOSink value "foldlM'" foldlM'Reduce
1411+ ]
1412+ , bgroup
1413+ "Identity"
1414+ [ benchIdentitySink value "foldl'" foldl'Reduce
1415+ , benchIdentitySink
1416+ value
1417+ "foldl1'"
1418+ foldl1'Reduce
1419+ , benchIdentitySink
1420+ value
1421+ "foldlM'"
1422+ foldlM'Reduce
1423+ ]
1424+ ]
1425+ , bgroup
1426+ "build"
1427+ [ bgroup
1428+ "IO"
1429+ [ benchIOSink
1430+ value
1431+ "foldrMElem"
1432+ (foldrMElem value)
1433+ ]
1434+ , bgroup
1435+ "Identity"
1436+ [ benchIdentitySink
1437+ value
1438+ "foldrMElem"
1439+ (foldrMElem value)
1440+ , benchIdentitySink
1441+ value
1442+ "foldrMToStreamLength"
1443+ (S.length . runIdentity . foldrMToStream)
1444+ , benchPureSink
1445+ value
1446+ "foldrMToListLength"
1447+ (P.length . runIdentity . foldrMBuild)
1448+ ]
1449+ ]
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
1470+ , benchHoistSink
1471+ value
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
1480+ ]
1481+ ]
1482+ ]
1483+
1484+o_1_space_serial_folds :: Int -> [Benchmark]
1485+o_1_space_serial_folds value =
1486+ [ bgroup
1487+ "serially"
1488+ [ bgroup
1489+ "folds"
1490+ [ benchIOSink value "drain" (S.fold FL.drain)
1491+ , benchIOSink value "drainN" (S.fold (IFL.drainN value))
1492+ , benchIOSink
1493+ value
1494+ "drainWhileTrue"
1495+ (S.fold (IFL.drainWhile $ (<=) (value + 1)))
1496+ , benchIOSink
1497+ value
1498+ "drainWhileFalse"
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)
1511+ , benchIOSink
1512+ value
1513+ "mean"
1514+ (\s ->
1515+ S.fold
1516+ FL.mean
1517+ (S.map (fromIntegral :: Int -> Double) s))
1518+ , benchIOSink
1519+ value
1520+ "variance"
1521+ (\s ->
1522+ S.fold
1523+ FL.variance
1524+ (S.map (fromIntegral :: Int -> Double) s))
1525+ , benchIOSink
1526+ value
1527+ "stdDev"
1528+ (\s ->
1529+ S.fold
1530+ FL.stdDev
1531+ (S.map (fromIntegral :: Int -> Double) s))
1532+ , benchIOSink
1533+ value
1534+ "mconcat"
1535+ (S.fold FL.mconcat . (S.map (Last . Just)))
1536+ , benchIOSink
1537+ value
1538+ "foldMap"
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))))
1543+ , benchIOSink
1544+ value
1545+ "findIndex"
1546+ (S.fold (FL.findIndex (== (value + 1))))
1547+ , benchIOSink
1548+ value
1549+ "elemIndex"
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))))
1556+ , benchIOSink
1557+ value
1558+ "and"
1559+ (\s -> S.fold FL.and (S.map (<= (value + 1)) s))
1560+ , benchIOSink
1561+ value
1562+ "or"
1563+ (\s -> S.fold FL.or (S.map (> (value + 1)) s))
1564+ ]
1565+ ]
1566+ ]
1567+
1568+o_1_space_serial_foldMultiStream :: Int -> [Benchmark]
1569+o_1_space_serial_foldMultiStream value =
1570+ [ bgroup
1571+ "serially"
1572+ [ bgroup
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
1579+ ]
1580+ ]
1581+ ]
1582+
1583+o_1_space_serial_foldsTransforms :: Int -> [Benchmark]
1584+o_1_space_serial_foldsTransforms value =
1585+ [ bgroup
1586+ "serially"
1587+ [ bgroup
1588+ "folds-transforms"
1589+ [ benchIOSink value "drain" (S.fold FL.drain)
1590+ , benchIOSink value "lmap" (S.fold (IFL.lmap (+ 1) FL.drain))
1591+ , benchIOSink
1592+ value
1593+ "pipe-mapM"
1594+ (S.fold
1595+ (IFL.transform
1596+ (Pipe.mapM (\x -> return $ x + 1))
1597+ FL.drain))
1598+ ]
1599+ ]
1600+ ]
1601+
1602+o_1_space_serial_foldsCompositions :: Int -> [Benchmark]
1603+o_1_space_serial_foldsCompositions value =
1604+ [ bgroup
1605+ "serially"
1606+ [ bgroup
1607+ "folds-compositions" -- Applicative
1608+ [ benchIOSink
1609+ value
1610+ "all,any"
1611+ (S.fold
1612+ ((,) <$> FL.all (<= (value + 1)) <*>
1613+ FL.any (> (value + 1))))
1614+ , benchIOSink
1615+ value
1616+ "sum,length"
1617+ (S.fold ((,) <$> FL.sum <*> FL.length))
1618+ ]
1619+ ]
1620+ ]
1621+
1622+o_1_space_serial_pipes :: Int -> [Benchmark]
1623+o_1_space_serial_pipes value =
1624+ [ bgroup
1625+ "serially"
1626+ [ bgroup
1627+ "pipes"
1628+ [ benchIOSink value "mapM" (transformMapM serially 1)
1629+ , benchIOSink
1630+ value
1631+ "compose"
1632+ (transformComposeMapM serially 1)
1633+ , benchIOSink value "tee" (transformTeeMapM serially 1)
1634+ , benchIOSink value "zip" (transformZipMapM serially 1)
1635+ ]
1636+ ]
1637+ ]
1638+
1639+o_1_space_serial_pipesX4 :: Int -> [Benchmark]
1640+o_1_space_serial_pipesX4 value =
1641+ [ bgroup
1642+ "serially"
1643+ [ bgroup
1644+ "pipesX4"
1645+ [ benchIOSink value "mapM" (transformMapM serially 4)
1646+ , benchIOSink
1647+ value
1648+ "compose"
1649+ (transformComposeMapM serially 4)
1650+ , benchIOSink value "tee" (transformTeeMapM serially 4)
1651+ , benchIOSink value "zip" (transformZipMapM serially 4)
1652+ ]
1653+ ]
1654+ ]
1655+
1656+
1657+o_1_space_serial_transformer :: Int -> [Benchmark]
1658+o_1_space_serial_transformer value =
1659+ [ bgroup
1660+ "serially"
1661+ [ bgroup
1662+ "transformer"
1663+ [ benchIOSrc serially "evalState" (evalStateT value)
1664+ , benchIOSrc serially "withState" (withState value)
1665+ ]
1666+ ]
1667+ ]
1668+
1669+o_1_space_serial_transformation :: Int -> [Benchmark]
1670+o_1_space_serial_transformation value =
1671+ [ bgroup
1672+ "serially"
1673+ [ bgroup
1674+ "transformation"
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" $
1683+ nfIO $
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)
1697+ ]
1698+ ]
1699+ ]
1700+
1701+o_1_space_serial_transformationX4 :: Int -> [Benchmark]
1702+o_1_space_serial_transformationX4 value =
1703+ [ bgroup
1704+ "serially"
1705+ [ bgroup
1706+ "transformationX4"
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)
1718+ ]
1719+ ]
1720+ ]
1721+
1722+o_1_space_serial_filtering :: Int -> [Benchmark]
1723+o_1_space_serial_filtering value =
1724+ [ bgroup
1725+ "serially"
1726+ [ bgroup
1727+ "filtering"
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)
1732+ , benchIOSink
1733+ value
1734+ "takeByTime-all"
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)
1741+ , benchIOSink
1742+ value
1743+ "dropByTime-all"
1744+ (dropByTime (NanoSecond64 maxBound) 1)
1745+ , benchIOSink value "dropWhile-true" (dropWhileTrue value 1)
1746+ --, benchIOSink value "dropWhileM-true" (dropWhileMTrue 1)
1747+ , benchIOSink
1748+ value
1749+ "dropWhile-false"
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)
1754+ ]
1755+ ]
1756+ ]
1757+
1758+o_1_space_serial_filteringX4 :: Int -> [Benchmark]
1759+o_1_space_serial_filteringX4 value =
1760+ [ bgroup
1761+ "serially"
1762+ [ bgroup
1763+ "filteringX4"
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)
1774+ , benchIOSink
1775+ value
1776+ "dropWhile-false"
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)
1781+ ]
1782+ ]
1783+ ]
1784+
1785+
1786+o_1_space_serial_joining :: Int -> [Benchmark]
1787+o_1_space_serial_joining value =
1788+ [ bgroup
1789+ "serially"
1790+ [ bgroup
1791+ "joining"
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)
1802+ ]
1803+ ]
1804+ ]
1805+
1806+
1807+o_1_space_serial_concatFoldable :: Int -> [Benchmark]
1808+o_1_space_serial_concatFoldable value =
1809+ [ bgroup
1810+ "serially"
1811+ [ bgroup
1812+ "concat-foldable"
1813+ [ benchIOSrc
1814+ serially
1815+ "foldMapWith"
1816+ (sourceFoldMapWith value)
1817+ , benchIOSrc
1818+ serially
1819+ "foldMapWithM"
1820+ (sourceFoldMapWithM value)
1821+ , benchIOSrc serially "foldMapM" (sourceFoldMapM value)
1822+ , benchIOSrc
1823+ serially
1824+ "foldWithConcatMapId"
1825+ (sourceConcatMapId value)
1826+ ]
1827+ ]
1828+ ]
1829+
1830+o_1_space_serial_concatSerial :: Int -> [Benchmark]
1831+o_1_space_serial_concatSerial value =
1832+ [ bgroup
1833+ "serially"
1834+ [ bgroup
1835+ "concat-serial"
1836+ [ benchIOSrc1
1837+ "concatMapPure (2,x/2)"
1838+ (concatMapPure 2 (value `div` 2))
1839+ , benchIOSrc1
1840+ "concatMap (2,x/2)"
1841+ (concatMap 2 (value `div` 2))
1842+ , benchIOSrc1
1843+ "concatMap (x/2,2)"
1844+ (concatMap (value `div` 2) 2)
1845+ , benchIOSrc1
1846+ "concatMapRepl (x/4,4)"
1847+ (concatMapRepl4xN value)
1848+ , benchIOSrc1
1849+ "concatUnfoldRepl (x/4,4)"
1850+ (concatUnfoldRepl4xN value)
1851+ , benchIOSrc1
1852+ "concatMapWithSerial (2,x/2)"
1853+ (concatMapWithSerial 2 (value `div` 2))
1854+ , benchIOSrc1
1855+ "concatMapWithSerial (x/2,2)"
1856+ (concatMapWithSerial (value `div` 2) 2)
1857+ , benchIOSrc1
1858+ "concatMapWithAppend (2,x/2)"
1859+ (concatMapWithAppend 2 (value `div` 2))
1860+ ]
1861+ ]
1862+ ]
1863+
1864+
1865+o_1_space_serial_outerProductStreams :: Int -> [Benchmark]
1866+o_1_space_serial_outerProductStreams value =
1867+ [ bgroup
1868+ "serially"
1869+ [ bgroup
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
1879+ ]
1880+ ]
1881+ ]
1882+
1883+
1884+o_1_space_serial_outerProductUnfolds :: Int -> [Benchmark]
1885+o_1_space_serial_outerProductUnfolds value =
1886+ [ bgroup
1887+ "serially"
1888+ [ bgroup
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
1897+ ]
1898+ ]
1899+ ]
1900+
1901+
1902+o_1_space_serial_mixed :: Int -> [Benchmark]
1903+o_1_space_serial_mixed value =
1904+ [ bgroup
1905+ "serially"
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.
1909+ [ bgroup
1910+ "mixed"
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
1915+ ]
1916+ ]
1917+ ]
1918+
1919+o_1_space_serial_mixedX4 :: Int -> [Benchmark]
1920+o_1_space_serial_mixedX4 value =
1921+ [ bgroup
1922+ "serially"
1923+ [ bgroup
1924+ "mixedX4"
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)
1936+ ]
1937+ ]
1938+ ]
1939+
1940+o_1_space_wSerial_transformation :: Int -> [Benchmark]
1941+o_1_space_wSerial_transformation value =
1942+ [ bgroup
1943+ "wSerially"
1944+ [ bgroup
1945+ "transformation"
1946+ [benchIOSink value "fmap" $ fmap' wSerially 1]
1947+ ]
1948+ ]
1949+
1950+o_1_space_wSerial_concatMap :: Int -> [Benchmark]
1951+o_1_space_wSerial_concatMap value =
1952+ [ bgroup
1953+ "wSerially"
1954+ [ bgroup
1955+ "concatMap"
1956+ [ benchIOSrc1
1957+ "concatMapWithWSerial (2,x/2)"
1958+ (concatMapWithWSerial 2 (value `div` 2))
1959+ , benchIOSrc1
1960+ "concatMapWithWSerial (x/2,2)"
1961+ (concatMapWithWSerial (value `div` 2) 2)
1962+ ]
1963+ ]
1964+ ]
1965+
1966+o_1_space_wSerial_outerProduct :: Int -> [Benchmark]
1967+o_1_space_wSerial_outerProduct value =
1968+ [ bgroup
1969+ "wSerially"
1970+ [ bgroup
1971+ "outer-product"
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
1980+ ]
1981+ ]
1982+ ]
1983+
1984+o_1_space_zipSerial_transformation :: Int -> [Benchmark]
1985+o_1_space_zipSerial_transformation value =
1986+ [ bgroup
1987+ "zipSerially"
1988+ [ bgroup
1989+ "transformation"
1990+ [benchIOSink value "fmap" $ fmap' zipSerially 1]
1991+ -- XXX needs fixing
1992+ {-
1993+ , bgroup "outer-product"
1994+ [ benchIO "toNullAp" $ Nested.toNullAp value zipSerially
1995+ ]
1996+ -}
1997+ ]
1998+ ]