on master help sign in
Elaborate concatMap, async benchmarks

* Add 3 interesting cases for each concatMap case * For mapM, map concurrently on a serial stream so that we measure the concurrency overhead of mapM only and not both concurrent generation + mapM * For Async streams add some benchmarks involving the `async` combinator. * Add a benchmark for `foldrS`

commitc0bd11de4ba32a8013a815df9063001d64459a8c authorHarendra Kumar <harendra@composewell.com> dateSun 21 Jun 2020, 01:38 (6 years ago) parentacf31ce
11 files changed+463−181
benchmark/Streamly/Benchmark/Data/Stream/StreamD.hs+96−18 benchmark/Streamly/Benchmark/Data/Stream/StreamK.hs+101−15 benchmark/Streamly/Benchmark/Prelude/Ahead.hs+23−14 benchmark/Streamly/Benchmark/Prelude/Async.hs+87−14 benchmark/Streamly/Benchmark/Prelude/Parallel.hs+23−15 benchmark/Streamly/Benchmark/Prelude/Serial.hs+78−51 benchmark/Streamly/Benchmark/Prelude/WAsync.hs+22−13 benchmark/Streamly/Benchmark/Prelude/WSerial.hs+8−8 benchmark/Streamly/Benchmark/Prelude/ZipAsync.hs+4−4 benchmark/Streamly/Benchmark/Prelude/ZipSerial.hs+10−7 benchmark/lib/Streamly/Benchmark/Prelude.hs+11−22
benchmark/Streamly/Benchmark/Data/Stream/StreamD.hs+96−18
@@ -5,9 +5,19 @@
55-- License : BSD3
66-- Maintainer : streamly@composewell.com
77
8+{-# LANGUAGE CPP #-}
89{-# LANGUAGE FlexibleContexts #-}
910{-# LANGUAGE ScopedTypeVariables #-}
1011
12+#ifdef __HADDOCK_VERSION__
13+#undef INSPECTION
14+#endif
15+
16+#ifdef INSPECTION
17+{-# LANGUAGE TemplateHaskell #-}
18+{-# OPTIONS_GHC -fplugin Test.Inspection.Plugin #-}
19+#endif
20+
1121module Main (main) where
1222
1323import Control.Monad (when)
@@ -22,6 +32,11 @@ import qualified Streamly.Internal.Data.Unfold as UF
2232
2333import Streamly.Benchmark.Common
2434
35+#ifdef INSPECTION
36+import GHC.Types (SPEC(..))
37+import Test.Inspection
38+#endif
39+
2540-- We try to keep the total number of iterations same irrespective of nesting
2641-- of the loops so that the overhead is easy to compare.
2742value, value2, value3, value16, maxValue :: Int
@@ -174,12 +189,11 @@ composeN n f =
174189{-# INLINE dropWhileFalse #-}
175190{-# INLINE _foldrS #-}
176191{-# INLINE _foldlS #-}
177−{-# INLINE concatMap #-}
178192{-# INLINE intersperse #-}
179193scan, map, fmapD, mapM, mapMaybe, mapMaybeM, filterEven, filterAllOut,
180194 filterAllIn, _takeOne, takeAll, takeWhileTrue, _takeWhileMTrue, dropOne,
181195 dropAll, dropWhileTrue, _dropWhileMTrue, dropWhileFalse, _foldrS, _foldlS,
182− concatMap, intersperse
196+ intersperse
183197 :: Monad m
184198 => Int -> Stream m Int -> m ()
185199
@@ -205,7 +219,6 @@ _dropWhileMTrue n = composeN n $ S.dropWhileM (return . (<= maxValue))
205219dropWhileFalse n = composeN n $ S.dropWhile (> maxValue)
206220_foldrS n = composeN n $ S.foldrS S.cons S.nil
207221_foldlS n = composeN n $ S.foldlS (flip S.cons) S.nil
208−concatMap n = composeN n $ (\s -> S.concatMap (\_ -> s) s)
209222intersperse n = composeN n $ S.intersperse maxValue
210223
211224-------------------------------------------------------------------------------
@@ -253,7 +266,7 @@ iterateM :: Monad m => Int -> Stream m Int
253266iterateM i = S.take maxIters (S.iterateM (\x -> return (x + 1)) (return i))
254267
255268-------------------------------------------------------------------------------
256−-- Zipping and concat
269+-- Zipping
257270-------------------------------------------------------------------------------
258271
259272{-# INLINE eqBy #-}
@@ -268,14 +281,6 @@ cmpBy src = S.cmpBy P.compare src src
268281zip :: Monad m => Stream m Int -> m ()
269282zip src = transform $ S.zipWith (,) src src
270283
271−{-# INLINE concatMapRepl4xN #-}
272−concatMapRepl4xN :: Monad m => Stream m Int -> m ()
273−concatMapRepl4xN src = transform $ (S.concatMap (S.replicate 4) src)
274−
275−{-# INLINE concatMapURepl4xN #-}
276−concatMapURepl4xN :: Monad m => Stream m Int -> m ()
277−concatMapURepl4xN src = transform $ S.concatMapU (UF.replicateM 4) src
278−
279284-------------------------------------------------------------------------------
280285-- Mixed Composition
281286-------------------------------------------------------------------------------
@@ -353,6 +358,63 @@ filterAllInNested str = runStream $ do
353358 then return s
354359 else S.nil
355360
361+-------------------------------------------------------------------------------
362+-- ConcatMap
363+-------------------------------------------------------------------------------
364+
365+-- concatMap unfoldrM/unfoldrM
366+
367+{-# INLINE concatMap #-}
368+concatMap :: Int -> Int -> Int -> IO ()
369+concatMap outer inner n =
370+ S.drain $ S.concatMap
371+ (\_ -> sourceUnfoldrMN inner n)
372+ (sourceUnfoldrMN outer n)
373+
374+#ifdef INSPECTION
375+inspect $ hasNoTypeClasses 'concatMap
376+inspect $ 'concatMap `hasNoType` ''SPEC
377+#endif
378+
379+-- concatMap unfoldr/unfoldr
380+
381+{-# INLINE concatMapPure #-}
382+concatMapPure :: Int -> Int -> Int -> IO ()
383+concatMapPure outer inner n =
384+ S.drain $ S.concatMap
385+ (\_ -> sourceUnfoldrN inner n)
386+ (sourceUnfoldrN outer n)
387+
388+#ifdef INSPECTION
389+inspect $ hasNoTypeClasses 'concatMapPure
390+inspect $ 'concatMapPure `hasNoType` ''SPEC
391+#endif
392+
393+-- concatMap replicate/unfoldrM
394+
395+{-# INLINE concatMapRepl #-}
396+concatMapRepl :: Int -> Int -> Int -> IO ()
397+concatMapRepl outer inner n =
398+ S.drain $ S.concatMap (S.replicate inner) (sourceUnfoldrMN outer n)
399+
400+#ifdef INSPECTION
401+inspect $ hasNoTypeClasses 'concatMapRepl
402+inspect $ 'concatMapRepl `hasNoType` ''SPEC
403+#endif
404+
405+-- concatUnfold replicate/unfoldrM
406+
407+{-# INLINE concatUnfoldRepl #-}
408+concatUnfoldRepl :: Int -> Int -> Int -> IO ()
409+concatUnfoldRepl outer inner n =
410+ S.drain $ S.concatMapU (UF.replicateM inner) (sourceUnfoldrMN outer n)
411+
412+#ifdef INSPECTION
413+inspect $ hasNoTypeClasses 'concatUnfoldRepl
414+inspect $ 'concatUnfoldRepl `hasNoType` ''S.ConcatMapUState
415+inspect $ 'concatUnfoldRepl `hasNoType` ''SPEC
416+#endif
417+
356418-------------------------------------------------------------------------------
357419-- Benchmarks
358420-------------------------------------------------------------------------------
@@ -396,12 +458,6 @@ o_1_space =
396458 , benchFold "mapM" (mapM 1) sourceUnfoldrM
397459 , benchFold "mapMaybe" (mapMaybe 1) sourceUnfoldrM
398460 , benchFold "mapMaybeM" (mapMaybeM 1) sourceUnfoldrM
399− , benchFold "concatMapNxN" (concatMap 1) (sourceUnfoldrMN value2)
400− , benchFold "concatMapRepl4xN" concatMapRepl4xN
401− (sourceUnfoldrMN (value `div` 4))
402− , benchFold "concatMapPureNxN" (concatMap 1) (sourceUnfoldrN value2)
403− , benchFold "concatMapURepl4xN" concatMapURepl4xN
404− (sourceUnfoldrMN (value `div` 4))
405461 ]
406462 , bgroup "transformationX4"
407463 [ benchFold "scan" (scan 4) sourceUnfoldrM
@@ -413,6 +469,28 @@ o_1_space =
413469 -- XXX this is horribly slow
414470 -- , benchFold "concatMap" (concatMap 4) (sourceUnfoldrMN value16)
415471 ]
472+
473+ , bgroup "concat"
474+ [ benchIOSrc1 "concatMapPure (n of 1)"
475+ (concatMapPure value 1)
476+ , benchIOSrc1 "concatMapPure (sqrt n of sqrt n)"
477+ (concatMapPure value2 value2)
478+ , benchIOSrc1 "concatMapPure (1 of n)"
479+ (concatMapPure 1 value)
480+
481+ , benchIOSrc1 "concatMap (n of 1)"
482+ (concatMap value 1)
483+ , benchIOSrc1 "concatMap (sqrt n of sqrt n)"
484+ (concatMap value2 value2)
485+ , benchIOSrc1 "concatMap (1 of n)"
486+ (concatMap 1 value)
487+
488+ -- concatMap vs concatUnfold
489+ , benchIOSrc1 "concatMapRepl (sqrt n of sqrt n)"
490+ (concatMapRepl value2 value2)
491+ , benchIOSrc1 "concatUnfoldRepl (sqrt n of sqrt n)"
492+ (concatUnfoldRepl value2 value2)
493+ ]
416494 , bgroup "filtering"
417495 [ benchFold "filter-even" (filterEven 1) sourceUnfoldrM
418496 , benchFold "filter-all-out" (filterAllOut 1) sourceUnfoldrM
benchmark/Streamly/Benchmark/Data/Stream/StreamK.hs+101−15
@@ -5,9 +5,19 @@
55-- License : BSD3
66-- Maintainer : streamly@composewell.com
77
8+{-# LANGUAGE CPP #-}
89{-# LANGUAGE FlexibleContexts #-}
910{-# LANGUAGE ScopedTypeVariables #-}
1011
12+#ifdef __HADDOCK_VERSION__
13+#undef INSPECTION
14+#endif
15+
16+#ifdef INSPECTION
17+{-# LANGUAGE TemplateHaskell #-}
18+{-# OPTIONS_GHC -fplugin Test.Inspection.Plugin #-}
19+#endif
20+
1121module Main (main) where
1222
1323import Control.Monad (when)
@@ -27,6 +37,10 @@ import Gauge (bench, nfIO, bgroup, Benchmark, defaultMain)
2737
2838import Streamly.Benchmark.Common
2939
40+#ifdef INSPECTION
41+import Test.Inspection
42+#endif
43+
3044value, value2, value3, value16, maxValue :: Int
3145value = 100000
3246value2 = round (P.fromIntegral value**(1/2::P.Double)) -- double nested loop
@@ -190,10 +204,9 @@ composeN n f =
190204{-# INLINE dropWhileFalse #-}
191205{-# INLINE foldrS #-}
192206{-# INLINE foldlS #-}
193−{-# INLINE concatMap #-}
194207scan, map, fmapK, filterEven, filterAllOut,
195208 filterAllIn, _takeOne, takeAll, takeWhileTrue, dropAll, dropOne,
196− dropWhileTrue, dropWhileFalse, foldrS, foldlS, concatMap
209+ dropWhileTrue, dropWhileFalse, foldrS, foldlS
197210 :: Monad m
198211 => Int -> Stream m Int -> m ()
199212
@@ -220,9 +233,6 @@ dropWhileTrue n = composeN n $ S.dropWhile (<= maxValue)
220233dropWhileFalse n = composeN n $ S.dropWhile (<= 1)
221234foldrS n = composeN n $ S.foldrS S.cons S.nil
222235foldlS n = composeN n $ S.foldlS (flip S.cons) S.nil
223−-- We use a (sqrt n) element stream as source and then concat the same stream
224−-- for each element to produce an n element stream.
225−concatMap n = composeN n $ (\s -> S.concatMap (\_ -> s) s)
226236intersperse n = composeN n $ S.intersperse maxValue
227237
228238-------------------------------------------------------------------------------
@@ -266,15 +276,11 @@ iterateDropOne = iterateSource (S.drop 1) maxIters
266276iterateDropWhileTrue = iterateSource (S.dropWhile (<= maxValue)) maxIters
267277
268278-------------------------------------------------------------------------------
269−-- Zipping and concat
279+-- Zipping
270280-------------------------------------------------------------------------------
271281
272282zip src = transform $ S.zipWith (,) src src
273283
274−{-# INLINE concatMapRepl4xN #-}
275−concatMapRepl4xN :: Monad m => Stream m Int -> m ()
276−concatMapRepl4xN src = transform $ (S.concatMap (S.replicate 4) src)
277−
278284-------------------------------------------------------------------------------
279285-- Mixed Composition
280286-------------------------------------------------------------------------------
@@ -304,6 +310,62 @@ filterTake n = composeN n $ S.take maxValue . S.filter (<= maxValue)
304310filterScan n = composeN n $ S.scanl' (+) 0 . S.filter (<= maxBound)
305311filterMap n = composeN n $ S.map (subtract 1) . S.filter (<= maxValue)
306312
313+-------------------------------------------------------------------------------
314+-- ConcatMap
315+-------------------------------------------------------------------------------
316+
317+-- concatMap unfoldrM/unfoldrM
318+
319+{-# INLINE concatMap #-}
320+concatMap :: Int -> Int -> Int -> IO ()
321+concatMap outer inner n =
322+ S.drain $ S.concatMap
323+ (\_ -> sourceUnfoldrMN inner n)
324+ (sourceUnfoldrMN outer n)
325+
326+#ifdef INSPECTION
327+inspect $ hasNoTypeClasses 'concatMap
328+#endif
329+
330+-- concatMap unfoldr/unfoldr
331+
332+{-# INLINE concatMapPure #-}
333+concatMapPure :: Int -> Int -> Int -> IO ()
334+concatMapPure outer inner n =
335+ S.drain $ S.concatMap
336+ (\_ -> sourceUnfoldrN inner n)
337+ (sourceUnfoldrN outer n)
338+
339+#ifdef INSPECTION
340+inspect $ hasNoTypeClasses 'concatMapPure
341+#endif
342+
343+-- concatMap replicate/unfoldrM
344+
345+{-# INLINE concatMapRepl #-}
346+concatMapRepl :: Int -> Int -> Int -> IO ()
347+concatMapRepl outer inner n =
348+ S.drain $ S.concatMap (S.replicate inner) (sourceUnfoldrMN outer n)
349+
350+#ifdef INSPECTION
351+inspect $ hasNoTypeClasses 'concatMapRepl
352+#endif
353+
354+-- concatMapWith
355+
356+{-# INLINE sourceConcatMapId #-}
357+sourceConcatMapId :: Monad m
358+ => Int -> Int -> Stream m (Stream m Int)
359+sourceConcatMapId val n =
360+ S.fromFoldable $ fmap (S.yieldM . return) [n..n+val]
361+
362+{-# INLINE concatStreamsWith #-}
363+concatStreamsWith :: Int -> Int -> Int -> IO ()
364+concatStreamsWith outer inner n =
365+ S.drain $ S.concatMapBy S.serial
366+ (sourceUnfoldrMN inner)
367+ (sourceUnfoldrMN outer n)
368+
307369-------------------------------------------------------------------------------
308370-- Nested Composition
309371-------------------------------------------------------------------------------
@@ -452,11 +514,6 @@ o_1_space =
452514 , benchFold "fmap" (fmapK 1) sourceUnfoldrM
453515 , benchFold "mapM" (mapM 1) sourceUnfoldrM
454516 , benchFold "mapMSerial" (mapMSerial 1) sourceUnfoldrM
455− -- , benchFoldSrcK "concatMap" concatMap
456− , benchFold "concatMapNxN" (concatMap 1) (sourceUnfoldrMN value2)
457− , benchFold "concatMapPureNxN" (concatMap 1) (sourceUnfoldrN value2)
458− , benchFold "concatMapRepl4xN" concatMapRepl4xN
459− (sourceUnfoldrMN (value `div` 4))
460517 ]
461518 , bgroup "transformationX4"
462519 [ benchFold "scan" (scan 4) sourceUnfoldrM
@@ -467,6 +524,35 @@ o_1_space =
467524 -- XXX this is horribly slow
468525 -- , benchFold "concatMap" (concatMap 4) (sourceUnfoldrMN value16)
469526 ]
527+ , bgroup "concat"
528+ [ benchIOSrc1 "concatMapPure (n of 1)"
529+ (concatMapPure value 1)
530+ , benchIOSrc1 "concatMapPure (sqrt n of sqrt n)"
531+ (concatMapPure value2 value2)
532+ , benchIOSrc1 "concatMapPure (1 of n)"
533+ (concatMapPure 1 value)
534+
535+ , benchIOSrc1 "concatMap (n of 1)"
536+ (concatMap value 1)
537+ , benchIOSrc1 "concatMap (sqrt n of sqrt n)"
538+ (concatMap value2 value2)
539+ , benchIOSrc1 "concatMap (1 of n)"
540+ (concatMap 1 value)
541+
542+ , benchIOSrc1 "concatMapRepl (sqrt n of sqrt n)"
543+ (concatMapRepl value2 value2)
544+
545+ -- This is for comparison with foldMapWith
546+ , benchIOSrc1 "concatMapWithId (n of 1) (fromFoldable)"
547+ (S.drain . S.concatMapBy S.serial id . sourceConcatMapId value)
548+
549+ , benchIOSrc1 "concatMapWith (n of 1)"
550+ (concatStreamsWith value 1)
551+ , benchIOSrc1 "concatMapWith (sqrt n of sqrt n)"
552+ (concatStreamsWith value2 value2)
553+ , benchIOSrc1 "concatMapWith (1 of n)"
554+ (concatStreamsWith 1 value)
555+ ]
470556 , bgroup "filtering"
471557 [ benchFold "filter-even" (filterEven 1) sourceUnfoldrM
472558 , benchFold "filter-all-out" (filterAllOut 1) sourceUnfoldrM
benchmark/Streamly/Benchmark/Prelude/Ahead.hs+23−14
@@ -7,7 +7,8 @@
77
88import Prelude hiding (mapM)
99
10−import Streamly (aheadly, ahead, maxBuffer, maxThreads)
10+import Streamly (aheadly, serially, ahead, maxBuffer, maxThreads)
11+import qualified Streamly.Prelude as S
1112
1213import Streamly.Benchmark.Common
1314import Streamly.Benchmark.Prelude
@@ -28,12 +29,12 @@ o_1_space_generation value =
2829 [ bgroup "generation"
2930 [ benchIOSrc aheadly "unfoldr" (sourceUnfoldr value)
3031 , benchIOSrc aheadly "unfoldrM" (sourceUnfoldrM value)
31− -- , benchIOSrc aheadly "fromFoldable" (sourceFromFoldable value)
32+ , benchIOSrc aheadly "fromFoldable" (sourceFromFoldable value)
3233 , benchIOSrc aheadly "fromFoldableM" (sourceFromFoldableM value)
3334 , benchIOSrc aheadly "unfoldrM maxThreads 1"
3435 (maxThreads 1 . sourceUnfoldrM value)
3536 , benchIOSrc aheadly "unfoldrM maxBuffer 1 (x/10 ops)"
36− (maxBuffer 1 . sourceUnfoldrMN (value `div` 10))
37+ (maxBuffer 1 . sourceUnfoldrM (value `div` 10))
3738 ]
3839 ]
3940
@@ -42,7 +43,7 @@ o_1_space_mapping value =
4243 [ bgroup "mapping"
4344 [ benchIOSink value "map" $ mapN aheadly 1
4445 , benchIOSink value "fmap" $ fmapN aheadly 1
45− , benchIOSink value "mapM" $ mapM aheadly 1
46+ , benchIOSink value "mapM" $ mapM aheadly 1 . serially
4647 ]
4748 ]
4849
@@ -50,9 +51,13 @@ o_1_space_concatFoldable :: Int -> [Benchmark]
5051o_1_space_concatFoldable value =
5152 [ bgroup
5253 "concat-foldable"
53− [ benchIOSrc aheadly "foldMapWith" (sourceFoldMapWith value)
54− , benchIOSrc aheadly "foldMapWithM" (sourceFoldMapWithM value)
55− , benchIOSrc aheadly "foldMapM" (sourceFoldMapM value)
54+ [ benchIOSrc aheadly "foldMapWith (<>) (List)"
55+ (sourceFoldMapWith value)
56+ , benchIOSrc aheadly "foldMapWith (<>) (Stream)"
57+ (sourceFoldMapWithStream value)
58+ , benchIOSrc aheadly "foldMapWithM (<>) (List)"
59+ (sourceFoldMapWithM value)
60+ , benchIOSrc aheadly "foldMapM (List)" (sourceFoldMapM value)
5661 ]
5762 ]
5863
@@ -60,13 +65,17 @@ o_1_space_concatMap :: Int -> [Benchmark]
6065o_1_space_concatMap value =
6166 value2 `seq`
6267 [ bgroup "concat"
63− [ benchIO "concatMapWith (2,x/2)"
64− (concatStreamsWith ahead 2 (value `div` 2))
65− , benchIO "concatMapWith (sqrt x,sqrt x)"
66− (concatStreamsWith ahead value2 value2)
67− , benchIO "concatMapWith (sqrt x * 2,sqrt x / 2)"
68− (concatStreamsWith ahead (value2 * 2) (value2 `div` 2))
69− ]
68+ -- This is for comparison with foldMapWith
69+ [ benchIOSrc serially "concatMapWithId (n of 1) (fromFoldable)"
70+ (S.concatMapWith ahead id . sourceConcatMapId value)
71+
72+ , benchIO "concatMapWith (n of 1)"
73+ (concatStreamsWith ahead value 1)
74+ , benchIO "concatMapWith (sqrt x of sqrt x)"
75+ (concatStreamsWith ahead value2 value2)
76+ , benchIO "concatMapWith (1 of n)"
77+ (concatStreamsWith ahead 1 value)
78+ ]
7079 ]
7180
7281 where
benchmark/Streamly/Benchmark/Prelude/Async.hs+87−14
@@ -7,7 +7,9 @@
77
88import Prelude hiding (mapM)
99
10−import Streamly (asyncly, async, maxBuffer, maxThreads)
10+import Streamly (asyncly, async, maxBuffer, maxThreads, serially)
11+import qualified Streamly.Prelude as S
12+import qualified Streamly.Internal.Prelude as Internal
1113
1214import Streamly.Benchmark.Common
1315import Streamly.Benchmark.Prelude
@@ -23,15 +25,17 @@ moduleName = "Prelude.Async"
2325
2426o_1_space_generation :: Int -> [Benchmark]
2527o_1_space_generation value =
28+ -- These basically test the performance of consMAsync
2629 [ bgroup "generation"
2730 [ benchIOSrc asyncly "unfoldr" (sourceUnfoldr value)
2831 , benchIOSrc asyncly "unfoldrM" (sourceUnfoldrM value)
29− , benchIOSrc asyncly "fromFoldable" (sourceFromFoldable value)
30− , benchIOSrc asyncly "fromFoldableM" (sourceFromFoldableM value)
32+ , benchIOSrc asyncly "fromListM" (sourceFromListM value)
33+ , benchIOSrc asyncly "fromFoldable (List)" (sourceFromFoldable value)
34+ , benchIOSrc asyncly "fromFoldableM (List)" (sourceFromFoldableM value)
3135 , benchIOSrc asyncly "unfoldrM maxThreads 1"
3236 (maxThreads 1 . sourceUnfoldrM value)
3337 , benchIOSrc asyncly "unfoldrM maxBuffer 1 (x/10 ops)"
34− (maxBuffer 1 . sourceUnfoldrMN (value `div` 10))
38+ (maxBuffer 1 . sourceUnfoldrM (value `div` 10))
3539 ]
3640 ]
3741
@@ -39,12 +43,69 @@ o_1_space_generation value =
3943-- Mapping
4044-------------------------------------------------------------------------------
4145
46+-- XXX this should be same as mapM return
47+-- XXX this has quadratic slowdown with async, but works well on serial
48+-- streams.
49+{-# INLINE foldrS #-}
50+foldrS :: Int -> Int -> IO ()
51+foldrS count n =
52+ S.drain
53+ $ asyncly
54+ $ Internal.foldrS (\x xs -> S.consM (return x) xs) S.nil
55+ $ serially
56+ $ sourceUnfoldrM count n
57+
4258o_1_space_mapping :: Int -> [Benchmark]
4359o_1_space_mapping value =
4460 [ bgroup "mapping"
4561 [ benchIOSink value "map" $ mapN asyncly 1
4662 , benchIOSink value "fmap" $ fmapN asyncly 1
47− , benchIOSink value "mapM" $ mapM asyncly 1
63+ -- This basically tests the performance of consMAsync
64+ , benchIOSink value "mapM" $ mapM asyncly 1 . serially
65+ ]
66+ ]
67+
68+o_n_heap_mapping :: Int -> [Benchmark]
69+o_n_heap_mapping _value =
70+ [ bgroup "mapping"
71+ [ benchIOSrc1 "foldrS (600)" (foldrS 600)
72+ ]
73+ ]
74+
75+-------------------------------------------------------------------------------
76+-- Joining
77+-------------------------------------------------------------------------------
78+
79+{-# INLINE async2 #-}
80+async2 :: Int -> Int -> IO ()
81+async2 count n =
82+ S.drain $
83+ (sourceUnfoldrM count n) `async` (sourceUnfoldrM count (n + 1))
84+
85+{-# INLINE async4 #-}
86+async4 :: Int -> Int -> IO ()
87+async4 count n =
88+ S.drain $
89+ (sourceUnfoldrM count (n + 0))
90+ `async` (sourceUnfoldrM count (n + 1))
91+ `async` (sourceUnfoldrM count (n + 2))
92+ `async` (sourceUnfoldrM count (n + 3))
93+
94+{-# INLINE async2n2 #-}
95+async2n2 :: Int -> Int -> IO ()
96+async2n2 count n =
97+ S.drain $
98+ ((sourceUnfoldrM count (n + 0))
99+ `async` (sourceUnfoldrM count (n + 1)))
100+ `async` ((sourceUnfoldrM count (n + 2))
101+ `async` (sourceUnfoldrM count (n + 3)))
102+
103+o_1_space_joining :: Int -> [Benchmark]
104+o_1_space_joining value =
105+ [ bgroup "joining"
106+ [ benchIOSrc1 "async (2 of n/2)" (async2 (value `div` 2))
107+ , benchIOSrc1 "async (4 of n/4)" (async4 (value `div` 4))
108+ , benchIOSrc1 "async (2 of (2 of n/4)" (async2n2 (value `div` 4))
48109 ]
49110 ]
50111
@@ -52,25 +113,35 @@ o_1_space_mapping value =
52113-- Concat
53114-------------------------------------------------------------------------------
54115
116+-- These basically test the performance of folding streams with `async`
55117o_1_space_concatFoldable :: Int -> [Benchmark]
56118o_1_space_concatFoldable value =
57119 [ bgroup "concat-foldable"
58− [ benchIOSrc asyncly "foldMapWith" (sourceFoldMapWith value)
59− , benchIOSrc asyncly "foldMapWithM" (sourceFoldMapWithM value)
60− , benchIOSrc asyncly "foldMapM" (sourceFoldMapM value)
120+ [ benchIOSrc asyncly "foldMapWith (<>) (List)"
121+ (sourceFoldMapWith value)
122+ , benchIOSrc asyncly "foldMapWith (<>) (Stream)"
123+ (sourceFoldMapWithStream value)
124+ , benchIOSrc asyncly "foldMapWithM (<>) (List)"
125+ (sourceFoldMapWithM value)
126+ , benchIOSrc asyncly "foldMapM (List)" (sourceFoldMapM value)
61127 ]
62128 ]
63129
130+-- These basically test the performance of concating streams with `async`
64131o_1_space_concatMap :: Int -> [Benchmark]
65132o_1_space_concatMap value =
66133 value2 `seq`
67− [ bgroup "concatMap"
68− [ benchIO "concatMapWith (2,x/2)"
69− (concatStreamsWith async 2 (value `div` 2))
70− , benchIO "concatMapWith (sqrt x,sqrt x)"
134+ [ bgroup "concat"
135+ -- This is for comparison with foldMapWith
136+ [ benchIOSrc serially "concatMapWithId (n of 1) (fromFoldable)"
137+ (S.concatMapWith async id . sourceConcatMapId value)
138+
139+ , benchIO "concatMapWith (n of 1)"
140+ (concatStreamsWith async value 1)
141+ , benchIO "concatMapWith (sqrt x of sqrt x)"
71142 (concatStreamsWith async value2 value2)
72− , benchIO "concatMapWith (sqrt x * 2,sqrt x / 2)"
73− (concatStreamsWith async (value2 * 2) (value2 `div` 2))
143+ , benchIO "concatMapWith (1 of n)"
144+ (concatStreamsWith async 1 value)
74145 ]
75146 ]
76147
@@ -122,6 +193,8 @@ main = do
122193 , o_1_space_concatFoldable value
123194 , o_1_space_concatMap value
124195 , o_1_space_outerProduct value
196+ , o_1_space_joining value
125197 ]
198+ , bgroup (o_n_heap_prefix moduleName) (o_n_heap_mapping value)
126199 , bgroup (o_n_space_prefix moduleName) (o_n_space_outerProduct value)
127200 ]
benchmark/Streamly/Benchmark/Prelude/Parallel.hs+23−15
@@ -34,16 +34,16 @@ mergeAsyncByM :: (S.IsStream t, S.MonadAsync m) => Int -> Int -> t m Int
3434mergeAsyncByM count n =
3535 S.mergeAsyncByM
3636 (\a b -> return (a `compare` b))
37− (sourceUnfoldrMN count n)
38− (sourceUnfoldrMN count (n + 1))
37+ (sourceUnfoldrM count n)
38+ (sourceUnfoldrM count (n + 1))
3939
4040{-# INLINE mergeAsyncBy #-}
4141mergeAsyncBy :: (S.IsStream t, S.MonadAsync m) => Int -> Int -> t m Int
4242mergeAsyncBy count n =
4343 S.mergeAsyncBy
4444 compare
45− (sourceUnfoldrMN count n)
46− (sourceUnfoldrMN count (n + 1))
45+ (sourceUnfoldrM count n)
46+ (sourceUnfoldrM count (n + 1))
4747
4848-------------------------------------------------------------------------------
4949-- Application/fold
@@ -99,7 +99,7 @@ o_n_heap_generation value =
9999 , benchIOSrc parallely "unfoldrM maxThreads 1"
100100 (maxThreads 1 . sourceUnfoldrM value)
101101 , benchIOSrc parallely "unfoldrM maxBuffer 1 (x/10 ops)"
102− (maxBuffer 1 . sourceUnfoldrMN (value `div` 10))
102+ (maxBuffer 1 . sourceUnfoldrM (value `div` 10))
103103 ]
104104 ]
105105
@@ -112,7 +112,7 @@ o_n_heap_mapping value =
112112 [ bgroup "mapping"
113113 [ benchIOSink value "map" $ mapN parallely 1
114114 , benchIOSink value "fmap" $ fmapN parallely 1
115− , benchIOSink value "mapM" $ mapM parallely 1
115+ , benchIOSink value "mapM" $ mapM parallely 1 . serially
116116 ]
117117 ]
118118
@@ -124,9 +124,13 @@ o_n_heap_concatFoldable :: Int -> [Benchmark]
124124o_n_heap_concatFoldable value =
125125 [ bgroup
126126 "concat-foldable"
127− [ benchIOSrc parallely "foldMapWith" (sourceFoldMapWith value)
128− , benchIOSrc parallely "foldMapWithM" (sourceFoldMapWithM value)
129− , benchIOSrc parallely "foldMapM" (sourceFoldMapM value)
127+ [ benchIOSrc parallely "foldMapWith (<>) (List)"
128+ (sourceFoldMapWith value)
129+ , benchIOSrc parallely "foldMapWith (<>) (Stream)"
130+ (sourceFoldMapWithStream value)
131+ , benchIOSrc parallely "foldMapWithM (<>) (List)"
132+ (sourceFoldMapWithM value)
133+ , benchIOSrc parallely "foldMapM (List)" (sourceFoldMapM value)
130134 ]
131135 ]
132136
@@ -134,12 +138,16 @@ o_n_heap_concat :: Int -> [Benchmark]
134138o_n_heap_concat value =
135139 value2 `seq`
136140 [ bgroup "concat"
137− [ benchIO "concatMapWith (2,x/2)"
138− (concatStreamsWith parallel 2 (value `div` 2))
139− , benchIO "concatMapWith (sqrt x,sqrt x)"
140− (concatStreamsWith parallel value2 value2)
141− , benchIO "concatMapWith (sqrt x * 2,sqrt x / 2)"
142− (concatStreamsWith parallel (value2 * 2) (value2 `div` 2))
141+ -- This is for comparison with foldMapWith
142+ [ benchIOSrc serially "concatMapWithId (n of 1) (fromFoldable)"
143+ (S.concatMapWith parallel id . sourceConcatMapId value)
144+
145+ , benchIO "concatMapWith (n of 1)"
146+ (concatStreamsWith parallel value 1)
147+ , benchIO "concatMapWith (sqrt x of sqrt x)"
148+ (concatStreamsWith parallel value2 value2)
149+ , benchIO "concatMapWith (1 of n)"
150+ (concatStreamsWith parallel 1 value)
143151 ]
144152 ]
145153
benchmark/Streamly/Benchmark/Prelude/Serial.hs+78−51
@@ -1216,7 +1216,7 @@ iterateSource ::
12161216 -> Int
12171217 -> Int
12181218 -> SerialT m Int
1219−iterateSource g i n = f i (sourceUnfoldrMN iterStreamLen n)
1219+iterateSource g i n = f i (sourceUnfoldrM iterStreamLen n)
12201220 where
12211221 f (0 :: Int) m = g m
12221222 f x m = g (f (x P.- 1) m)
@@ -1324,23 +1324,23 @@ o_1_space_pipesX4 value =
13241324serial2 :: Int -> Int -> IO ()
13251325serial2 count n =
13261326 S.drain $
1327− S.serial (sourceUnfoldrMN count n) (sourceUnfoldrMN count (n + 1))
1327+ S.serial (sourceUnfoldrM count n) (sourceUnfoldrM count (n + 1))
13281328
13291329{-# INLINE serial4 #-}
13301330serial4 :: Int -> Int -> IO ()
13311331serial4 count n =
13321332 S.drain $
13331333 S.serial
1334− (S.serial (sourceUnfoldrMN count n) (sourceUnfoldrMN count (n + 1)))
1334+ (S.serial (sourceUnfoldrM count n) (sourceUnfoldrM count (n + 1)))
13351335 (S.serial
1336− (sourceUnfoldrMN count (n + 2))
1337− (sourceUnfoldrMN count (n + 3)))
1336+ (sourceUnfoldrM count (n + 2))
1337+ (sourceUnfoldrM count (n + 3)))
13381338
13391339{-# INLINE append2 #-}
13401340append2 :: Int -> Int -> IO ()
13411341append2 count n =
13421342 S.drain $
1343− Internal.append (sourceUnfoldrMN count n) (sourceUnfoldrMN count (n + 1))
1343+ Internal.append (sourceUnfoldrM count n) (sourceUnfoldrM count (n + 1))
13441344
13451345{-# INLINE append4 #-}
13461346append4 :: Int -> Int -> IO ()
@@ -1348,11 +1348,11 @@ append4 count n =
13481348 S.drain $
13491349 Internal.append
13501350 (Internal.append
1351− (sourceUnfoldrMN count n)
1352− (sourceUnfoldrMN count (n + 1)))
1351+ (sourceUnfoldrM count n)
1352+ (sourceUnfoldrM count (n + 1)))
13531353 (Internal.append
1354− (sourceUnfoldrMN count (n + 2))
1355− (sourceUnfoldrMN count (n + 3)))
1354+ (sourceUnfoldrM count (n + 2))
1355+ (sourceUnfoldrM count (n + 3)))
13561356
13571357#ifdef INSPECTION
13581358inspect $ hasNoTypeClasses 'append2
@@ -1370,8 +1370,8 @@ mergeBy count n =
13701370 S.drain $
13711371 S.mergeBy
13721372 P.compare
1373− (sourceUnfoldrMN count n)
1374− (sourceUnfoldrMN count (n + 1))
1373+ (sourceUnfoldrM count n)
1374+ (sourceUnfoldrM count (n + 1))
13751375
13761376#ifdef INSPECTION
13771377inspect $ hasNoTypeClasses 'mergeBy
@@ -1397,10 +1397,13 @@ o_1_space_joining value =
13971397o_1_space_concatFoldable :: Int -> [Benchmark]
13981398o_1_space_concatFoldable value =
13991399 [ bgroup "concat-foldable"
1400− [ benchIOSrc serially "foldMapWith" (sourceFoldMapWith value)
1401− , benchIOSrc serially "foldMapWithM" (sourceFoldMapWithM value)
1402− , benchIOSrc serially "foldMapM" (sourceFoldMapM value)
1403− , benchIOSrc serially "foldWithConcatMapId" (sourceConcatMapId value)
1400+ [ benchIOSrc serially "foldMapWith (<>) (List)"
1401+ (sourceFoldMapWith value)
1402+ , benchIOSrc serially "foldMapWith (<>) (Stream)"
1403+ (sourceFoldMapWithStream value)
1404+ , benchIOSrc serially "foldMapWithM (<>) (List)"
1405+ (sourceFoldMapWithM value)
1406+ , benchIOSrc serially "foldMapM (List)" (sourceFoldMapM value)
14041407 ]
14051408 ]
14061409
@@ -1414,8 +1417,8 @@ o_1_space_concatFoldable value =
14141417concatMap :: Int -> Int -> Int -> IO ()
14151418concatMap outer inner n =
14161419 S.drain $ S.concatMap
1417− (\_ -> sourceUnfoldrMN inner n)
1418− (sourceUnfoldrMN outer n)
1420+ (\_ -> sourceUnfoldrM inner n)
1421+ (sourceUnfoldrM outer n)
14191422
14201423#ifdef INSPECTION
14211424inspect $ hasNoTypeClasses 'concatMap
@@ -1428,8 +1431,8 @@ inspect $ 'concatMap `hasNoType` ''SPEC
14281431concatMapPure :: Int -> Int -> Int -> IO ()
14291432concatMapPure outer inner n =
14301433 S.drain $ S.concatMap
1431− (\_ -> sourceUnfoldrN inner n)
1432− (sourceUnfoldrN outer n)
1434+ (\_ -> sourceUnfoldr inner n)
1435+ (sourceUnfoldr outer n)
14331436
14341437#ifdef INSPECTION
14351438inspect $ hasNoTypeClasses 'concatMapPure
@@ -1438,14 +1441,14 @@ inspect $ 'concatMapPure `hasNoType` ''SPEC
14381441
14391442-- concatMap replicate/unfoldrM
14401443
1441−{-# INLINE concatMapRepl4xN #-}
1442−concatMapRepl4xN :: Int -> Int -> IO ()
1443−concatMapRepl4xN value n = S.drain $ S.concatMap (S.replicate 4)
1444− (sourceUnfoldrMN (value `div` 4) n)
1444+{-# INLINE concatMapRepl #-}
1445+concatMapRepl :: Int -> Int -> Int -> IO ()
1446+concatMapRepl outer inner n =
1447+ S.drain $ S.concatMap (S.replicate inner) (sourceUnfoldrM outer n)
14451448
14461449#ifdef INSPECTION
1447−inspect $ hasNoTypeClasses 'concatMapRepl4xN
1448−inspect $ 'concatMapRepl4xN `hasNoType` ''SPEC
1450+inspect $ hasNoTypeClasses 'concatMapRepl
1451+inspect $ 'concatMapRepl `hasNoType` ''SPEC
14491452#endif
14501453
14511454-- concatMapWith
@@ -1472,41 +1475,65 @@ inspect $ 'concatMapWithAppend `hasNoType` ''SPEC
14721475
14731476-- concatUnfold replicate/unfoldrM
14741477
1475−{-# INLINE concatUnfoldRepl4xN #-}
1476−concatUnfoldRepl4xN :: Int -> Int -> IO ()
1477−concatUnfoldRepl4xN value n =
1478− S.drain $ S.concatUnfold
1479− (UF.replicateM 4)
1480− (sourceUnfoldrMN (value `div` 4) n)
1478+{-# INLINE concatUnfoldRepl #-}
1479+concatUnfoldRepl :: Int -> Int -> Int -> IO ()
1480+concatUnfoldRepl outer inner n =
1481+ S.drain $ S.concatUnfold (UF.replicateM inner) (sourceUnfoldrM outer n)
14811482
14821483#ifdef INSPECTION
1483−inspect $ hasNoTypeClasses 'concatUnfoldRepl4xN
1484−inspect $ 'concatUnfoldRepl4xN `hasNoType` ''D.ConcatMapUState
1485−inspect $ 'concatUnfoldRepl4xN `hasNoType` ''SPEC
1484+inspect $ hasNoTypeClasses 'concatUnfoldRepl
1485+inspect $ 'concatUnfoldRepl `hasNoType` ''D.ConcatMapUState
1486+inspect $ 'concatUnfoldRepl `hasNoType` ''SPEC
14861487#endif
14871488
14881489o_1_space_concat :: Int -> [Benchmark]
1489−o_1_space_concat value =
1490+o_1_space_concat value = sqrtVal `seq`
14901491 [ bgroup "concat"
1491− [ benchIOSrc1 "concatMapPure (2,x/2)"
1492− (concatMapPure 2 (value `div` 2))
1493− , benchIOSrc1 "concatMap (2,x/2)"
1494− (concatMap 2 (value `div` 2))
1495− , benchIOSrc1 "concatMap (x/2,2)"
1496− (concatMap (value `div` 2) 2)
1497− , benchIOSrc1 "concatMapRepl (x/4,4)"
1498− (concatMapRepl4xN value)
1499− , benchIOSrc1 "concatUnfoldRepl (x/4,4)"
1500− (concatUnfoldRepl4xN value)
1501− , benchIOSrc1 "concatMapWithSerial (2,x/2)"
1502− (concatMapWithSerial 2 (value `div` 2))
1503− , benchIOSrc1 "concatMapWithSerial (x/2,2)"
1504− (concatMapWithSerial (value `div` 2) 2)
1505− , benchIOSrc1 "concatMapWithAppend (2,x/2)"
1492+ [ benchIOSrc1 "concatMapPure (n of 1)"
1493+ (concatMapPure value 1)
1494+ , benchIOSrc1 "concatMapPure (sqrt n of sqrt n)"
1495+ (concatMapPure sqrtVal sqrtVal)
1496+ , benchIOSrc1 "concatMapPure (1 of n)"
1497+ (concatMapPure 1 value)
1498+
1499+ -- This is for comparison with foldMapWith
1500+ , benchIOSrc serially "concatMapId (n of 1) (fromFoldable)"
1501+ (S.concatMap id . sourceConcatMapId value)
1502+
1503+ , benchIOSrc1 "concatMap (n of 1)"
1504+ (concatMap value 1)
1505+ , benchIOSrc1 "concatMap (sqrt n of sqrt n)"
1506+ (concatMap sqrtVal sqrtVal)
1507+ , benchIOSrc1 "concatMap (1 of n)"
1508+ (concatMap 1 value)
1509+
1510+ -- This is for comparison with foldMapWith
1511+ , benchIOSrc serially "concatMapWithId (n of 1) (fromFoldable)"
1512+ (S.concatMapWith serial id . sourceConcatMapId value)
1513+
1514+ , benchIOSrc1 "concatMapWith (n of 1)"
1515+ (concatMapWithSerial value 1)
1516+ , benchIOSrc1 "concatMapWith (sqrt n of sqrt n)"
1517+ (concatMapWithSerial sqrtVal sqrtVal)
1518+ , benchIOSrc1 "concatMapWith (1 of n)"
1519+ (concatMapWithSerial 1 value)
1520+
1521+ -- quadratic with number of outer streams
1522+ , benchIOSrc1 "concatMapWithAppend (2 of n/2)"
15061523 (concatMapWithAppend 2 (value `div` 2))
1524+
1525+ -- concatMap vs concatUnfold
1526+ , benchIOSrc1 "concatMapRepl (sqrt n of sqrt n)"
1527+ (concatMapRepl sqrtVal sqrtVal)
1528+ , benchIOSrc1 "concatUnfoldRepl (sqrt n of sqrt n)"
1529+ (concatUnfoldRepl sqrtVal sqrtVal)
15071530 ]
15081531 ]
15091532
1533+ where
1534+
1535+ sqrtVal = round $ sqrt (fromIntegral value :: Double)
1536+
15101537-------------------------------------------------------------------------------
15111538-- Monad
15121539-------------------------------------------------------------------------------
benchmark/Streamly/Benchmark/Prelude/WAsync.hs+22−13
@@ -7,7 +7,8 @@
77
88import Prelude hiding (mapM)
99
10−import Streamly (wAsyncly, wAsync, maxBuffer, maxThreads)
10+import Streamly (wAsyncly, serially, wAsync, maxBuffer, maxThreads)
11+import qualified Streamly.Prelude as S
1112
1213import Streamly.Benchmark.Common
1314import Streamly.Benchmark.Prelude
@@ -31,7 +32,7 @@ o_1_space_generation value =
3132 , benchIOSrc wAsyncly "unfoldrM maxThreads 1"
3233 (maxThreads 1 . sourceUnfoldrM value)
3334 , benchIOSrc wAsyncly "unfoldrM maxBuffer 1 (x/10 ops)"
34− (maxBuffer 1 . sourceUnfoldrMN (value `div` 10))
35+ (maxBuffer 1 . sourceUnfoldrM (value `div` 10))
3536 ]
3637 ]
3738
@@ -44,7 +45,7 @@ o_1_space_mapping value =
4445 [ bgroup "mapping"
4546 [ benchIOSink value "map" $ mapN wAsyncly 1
4647 , benchIOSink value "fmap" $ fmapN wAsyncly 1
47− , benchIOSink value "mapM" $ mapM wAsyncly 1
48+ , benchIOSink value "mapM" $ mapM wAsyncly 1 . serially
4849 ]
4950 ]
5051
@@ -55,9 +56,13 @@ o_1_space_mapping value =
5556o_1_space_concatFoldable :: Int -> [Benchmark]
5657o_1_space_concatFoldable value =
5758 [ bgroup "concat-foldable"
58− [ benchIOSrc wAsyncly "foldMapWith" (sourceFoldMapWith value)
59− , benchIOSrc wAsyncly "foldMapWithM" (sourceFoldMapWithM value)
60− , benchIOSrc wAsyncly "foldMapM" (sourceFoldMapM value)
59+ [ benchIOSrc wAsyncly "foldMapWith (<>) (List)"
60+ (sourceFoldMapWith value)
61+ , benchIOSrc wAsyncly "foldMapWith (<>) (Stream)"
62+ (sourceFoldMapWithStream value)
63+ , benchIOSrc wAsyncly "foldMapWithM (<>) (List)"
64+ (sourceFoldMapWithM value)
65+ , benchIOSrc wAsyncly "foldMapM (List)" (sourceFoldMapM value)
6166 ]
6267 ]
6368
@@ -73,13 +78,17 @@ o_1_space_concatMap :: Int -> [Benchmark]
7378o_1_space_concatMap value =
7479 value2 `seq`
7580 [ bgroup "concat"
76− [ benchIO "concatMapWith (2,x/2)"
77− (concatStreamsWith wAsync 2 (value `div` 2))
78− , benchIO "concatMapWith (sqrt x,sqrt x)"
79− (concatStreamsWith wAsync value2 value2)
80− , benchIO "concatMapWith (sqrt x * 2,sqrt x / 2)"
81− (concatStreamsWith wAsync (value2 * 2) (value2 `div` 2))
82− ]
81+ -- This is for comparison with foldMapWith
82+ [ benchIOSrc serially "concatMapWithId (n of 1) (fromFoldable)"
83+ (S.concatMapWith wAsync id . sourceConcatMapId value)
84+
85+ , benchIO "concatMapWith (n of 1)"
86+ (concatStreamsWith wAsync value 1)
87+ , benchIO "concatMapWith (sqrt x of sqrt x)"
88+ (concatStreamsWith wAsync value2 value2)
89+ , benchIO "concatMapWith (1 of n)"
90+ (concatStreamsWith wAsync 1 value)
91+ ]
8392 ]
8493
8594 where
benchmark/Streamly/Benchmark/Prelude/WSerial.hs+8−8
@@ -57,16 +57,16 @@ o_1_space_mapping value =
5757wSerial2 :: Int -> Int -> IO ()
5858wSerial2 value n =
5959 S.drain $ wSerial
60− (sourceUnfoldrMN (value `div` 2) n)
61− (sourceUnfoldrMN (value `div` 2) (n + 1))
60+ (sourceUnfoldrM (value `div` 2) n)
61+ (sourceUnfoldrM (value `div` 2) (n + 1))
6262
6363{-# INLINE interleave2 #-}
6464interleave2 :: Int -> Int -> IO ()
6565interleave2 value n =
6666 S.drain $
6767 Internal.interleave
68− (sourceUnfoldrMN (value `div` 2) n)
69− (sourceUnfoldrMN (value `div` 2) (n + 1))
68+ (sourceUnfoldrM (value `div` 2) n)
69+ (sourceUnfoldrM (value `div` 2) (n + 1))
7070
7171#ifdef INSPECTION
7272inspect $ hasNoTypeClasses 'interleave2
@@ -79,8 +79,8 @@ roundRobin2 :: Int -> Int -> IO ()
7979roundRobin2 value n =
8080 S.drain $
8181 Internal.roundrobin
82− (sourceUnfoldrMN (value `div` 2) n)
83− (sourceUnfoldrMN (value `div` 2) (n + 1))
82+ (sourceUnfoldrM (value `div` 2) n)
83+ (sourceUnfoldrM (value `div` 2) (n + 1))
8484
8585#ifdef INSPECTION
8686inspect $ hasNoTypeClasses 'roundRobin2
@@ -127,7 +127,7 @@ concatUnfoldInterleaveRepl4xN :: Int -> Int -> IO ()
127127concatUnfoldInterleaveRepl4xN value n =
128128 S.drain $ Internal.concatUnfoldInterleave
129129 (UF.replicateM 4)
130− (sourceUnfoldrMN (value `div` 4) n)
130+ (sourceUnfoldrM (value `div` 4) n)
131131
132132#ifdef INSPECTION
133133inspect $ hasNoTypeClasses 'concatUnfoldInterleaveRepl4xN
@@ -141,7 +141,7 @@ concatUnfoldRoundrobinRepl4xN :: Int -> Int -> IO ()
141141concatUnfoldRoundrobinRepl4xN value n =
142142 S.drain $ Internal.concatUnfoldRoundrobin
143143 (UF.replicateM 4)
144− (sourceUnfoldrMN (value `div` 4) n)
144+ (sourceUnfoldrM (value `div` 4) n)
145145
146146#ifdef INSPECTION
147147inspect $ hasNoTypeClasses 'concatUnfoldRoundrobinRepl4xN
benchmark/Streamly/Benchmark/Prelude/ZipAsync.hs+4−4
@@ -26,21 +26,21 @@ moduleName = "Prelude.ZipAsync"
2626{-# INLINE zipAsync #-}
2727zipAsync :: (S.IsStream t, S.MonadAsync m) => Int -> Int -> t m (Int, Int)
2828zipAsync count n =
29− S.zipAsyncWith (,) (sourceUnfoldrMN count n) (sourceUnfoldrMN count (n + 1))
29+ S.zipAsyncWith (,) (sourceUnfoldrM count n) (sourceUnfoldrM count (n + 1))
3030
3131{-# INLINE zipAsyncM #-}
3232zipAsyncM :: (S.IsStream t, S.MonadAsync m) => Int -> Int -> t m (Int, Int)
3333zipAsyncM count n =
3434 S.zipAsyncWithM
3535 (curry return)
36− (sourceUnfoldrMN count n)
37− (sourceUnfoldrMN count (n + 1))
36+ (sourceUnfoldrM count n)
37+ (sourceUnfoldrM count (n + 1))
3838
3939{-# INLINE zipAsyncAp #-}
4040zipAsyncAp :: (S.IsStream t, S.MonadAsync m) => Int -> Int -> t m (Int, Int)
4141zipAsyncAp count n =
4242 S.zipAsyncly $
43− (,) <$> sourceUnfoldrMN count n <*> sourceUnfoldrMN count (n + 1)
43+ (,) <$> sourceUnfoldrM count n <*> sourceUnfoldrM count (n + 1)
4444
4545o_1_space_joining :: Int -> [Benchmark]
4646o_1_space_joining value =
benchmark/Streamly/Benchmark/Prelude/ZipSerial.hs+10−7
@@ -26,7 +26,7 @@ import qualified Streamly as S
2626import qualified Streamly.Prelude as S
2727
2828import Streamly.Benchmark.Common
29−import Streamly.Benchmark.Prelude hiding (sourceUnfoldrMN)
29+import Streamly.Benchmark.Prelude hiding (sourceUnfoldrM)
3030
3131import Gauge
3232
@@ -46,9 +46,9 @@ moduleName = "Prelude.ZipSerial"
4646
4747-- XXX somehow copying this definition here instead of importing it performs
4848-- better. Need to investigate why.
49−{-# INLINE sourceUnfoldrMN #-}
50−sourceUnfoldrMN :: (S.IsStream t, S.MonadAsync m) => Int -> Int -> t m Int
51−sourceUnfoldrMN count start = S.unfoldrM step start
49+{-# INLINE sourceUnfoldrM #-}
50+sourceUnfoldrM :: (S.IsStream t, S.MonadAsync m) => Int -> Int -> t m Int
51+sourceUnfoldrM count start = S.unfoldrM step start
5252 where
5353 step cnt =
5454 if cnt > start + count
@@ -59,7 +59,10 @@ sourceUnfoldrMN count start = S.unfoldrM step start
5959zip :: Int -> Int -> IO ()
6060zip count n =
6161 S.drain $
62− S.zipWith (,) (S.serially $ sourceUnfoldrMN count n) (S.serially $ sourceUnfoldrMN count (n + 1))
62+ S.zipWith
63+ (,)
64+ (S.serially $ sourceUnfoldrM count n)
65+ (S.serially $ sourceUnfoldrM count (n + 1))
6366
6467#ifdef INSPECTION
6568inspect $ hasNoTypeClasses 'zip
@@ -73,8 +76,8 @@ zipM count n =
7376 S.drain $
7477 S.zipWithM
7578 (curry return)
76− (sourceUnfoldrMN count n)
77− (sourceUnfoldrMN count (n + 1))
79+ (sourceUnfoldrM count n)
80+ (sourceUnfoldrM count (n + 1))
7881
7982#ifdef INSPECTION
8083inspect $ hasNoTypeClasses 'zipM
benchmark/lib/Streamly/Benchmark/Prelude.hs+11−22
@@ -14,6 +14,7 @@ module Streamly.Benchmark.Prelude where
1414
1515import Control.DeepSeq (NFData(..))
1616import Control.Exception (try)
17+import Data.Functor.Identity (Identity)
1718import GHC.Exception (ErrorCall)
1819import System.Random (randomRIO)
1920
@@ -72,15 +73,6 @@ sourceUnfoldr count start = S.unfoldr step start
7273 then Nothing
7374 else Just (cnt, cnt + 1)
7475
75−{-# INLINE sourceUnfoldrN #-}
76−sourceUnfoldrN :: (Monad m, S.IsStream t) => Int -> Int -> t m Int
77−sourceUnfoldrN count start = S.unfoldr step start
78− where
79− step cnt =
80− if cnt > start + count
81− then Nothing
82− else Just (cnt, cnt + 1)
83−
8476{-# INLINE sourceUnfoldrM #-}
8577sourceUnfoldrM :: (S.IsStream t, S.MonadAsync m) => Int -> Int -> t m Int
8678sourceUnfoldrM count start = S.unfoldrM step start
@@ -90,15 +82,6 @@ sourceUnfoldrM count start = S.unfoldrM step start
9082 then return Nothing
9183 else return (Just (cnt, cnt + 1))
9284
93−{-# INLINE sourceUnfoldrMN #-}
94−sourceUnfoldrMN :: (S.IsStream t, S.MonadAsync m) => Int -> Int -> t m Int
95−sourceUnfoldrMN count start = S.unfoldrM step start
96− where
97− step cnt =
98− if cnt > start + count
99− then return Nothing
100− else return (Just (cnt, cnt + 1))
101−
10285-------------------------------------------------------------------------------
10386-- fromIndices
10487-------------------------------------------------------------------------------
@@ -303,6 +286,12 @@ sourceFoldMapWith :: (S.IsStream t, S.Semigroup (t m Int))
303286 => Int -> Int -> t m Int
304287sourceFoldMapWith value n = S.foldMapWith (S.<>) S.yield [n..n+value]
305288
289+{-# INLINE sourceFoldMapWithStream #-}
290+sourceFoldMapWithStream :: (S.IsStream t, S.Semigroup (t m Int))
291+ => Int -> Int -> t m Int
292+sourceFoldMapWithStream value n = S.foldMapWith (S.<>) S.yield
293+ $ (S.enumerateFromTo n (n + value) :: S.SerialT Identity Int)
294+
306295{-# INLINE sourceFoldMapWithM #-}
307296sourceFoldMapWithM :: (S.IsStream t, Monad m, S.Semigroup (t m Int))
308297 => Int -> Int -> t m Int
@@ -320,9 +309,9 @@ sourceFoldMapM value n = F.foldMap (S.yieldM . return) [n..n+value]
320309
321310{-# INLINE sourceConcatMapId #-}
322311sourceConcatMapId :: (S.IsStream t, Monad m)
323− => Int -> Int -> t m Int
312+ => Int -> Int -> t m (t m Int)
324313sourceConcatMapId value n =
325− S.concatMap id $ S.fromFoldable $ fmap (S.yieldM . return) [n..n+value]
314+ S.fromFoldable $ fmap (S.yieldM . return) [n..n+value]
326315
327316-- concatMapWith
328317
@@ -335,8 +324,8 @@ concatStreamsWith
335324 -> IO ()
336325concatStreamsWith op outer inner n =
337326 S.drain $ S.concatMapWith op
338− (sourceUnfoldrMN inner)
339− (sourceUnfoldrMN outer n)
327+ (S.serially . sourceUnfoldrM inner)
328+ (S.serially $ sourceUnfoldrM outer n)
340329
341330-------------------------------------------------------------------------------
342331-- Monadic outer product