on master help sign in
Move and split benchmarks from O_1_Space.hs to Groups.hs

* Streamly/Benchmark/Prelude/O_1_Space.hs -> lib/Streamly/Benchmark/Groups.hs * Modify O_1_Space.hs accordingly

commit2dacf9948832e2304b321f0130b1d6611c20db33 authoradithyaov <adithya@composewell.com> dateWed 26 Feb 2020, 16:13 (7 years ago) parente754561
3 files changed+838−458
benchmark/Streamly/Benchmark/Prelude/Serial/O_1_Space.hs+41−457 benchmark/lib/Streamly/Benchmark/Groups.hs+792 benchmark/streamly-benchmarks.cabal+5−1
benchmark/Streamly/Benchmark/Prelude/Serial/O_1_Space.hs+41−457
@@ -5,80 +5,10 @@
55-- License : BSD3
66-- Maintainer : streamly@composewell.com
77
8−import Control.DeepSeq (NFData(..))
9−import Data.Functor.Identity (Identity, runIdentity)
10−import Data.Monoid (Last(..))
11−import System.Random (randomRIO)
12−
13−import qualified GHC.Exts as GHC
14−import qualified Streamly.Benchmark.Prelude as Ops
15−
16−import Streamly
17−import qualified Streamly.Data.Fold as FL
18−import qualified Streamly.Prelude as S
19−import qualified Streamly.Internal.Data.Sink as Sink
20−
21−import Streamly.Internal.Data.Time.Units
22−import qualified Streamly.Internal.Memory.Array as IA
23−import qualified Streamly.Internal.Data.Fold as IFL
24−import qualified Streamly.Internal.Prelude as IP
25−import qualified Streamly.Internal.Data.Pipe as Pipe
26−
27−import qualified NestedOps as Nested
28−import qualified NestedUnfoldOps as NestedUnfold
29−
30−import Gauge
318import Streamly.Benchmark.Common
9+import Streamly.Benchmark.Groups
3210
33−-------------------------------------------------------------------------------
34−--
35−-------------------------------------------------------------------------------
36−
37−-- We need a monadic bind here to make sure that the function f does not get
38−-- completely optimized out by the compiler in some cases.
39−
40−-- | Takes a fold method, and uses it with a default source.
41−{-# INLINE benchIOSink #-}
42−benchIOSink
43− :: (IsStream t, NFData b)
44− => Int -> String -> (t IO Int -> IO b) -> Benchmark
45−benchIOSink value name f = bench name $ nfIO $ randomRIO (1,1) >>= f . Ops.source value
46−
47−{-# INLINE benchHoistSink #-}
48−benchHoistSink
49− :: (IsStream t, NFData b)
50− => Int -> String -> (t Identity Int -> IO b) -> Benchmark
51−benchHoistSink value name f =
52− bench name $ nfIO $ randomRIO (1,1) >>= f . Ops.sourceUnfoldr value
53−
54−-- XXX We should be using sourceUnfoldrM for fair comparison with IO monad, but
55−-- we can't use it as it requires MonadAsync constraint.
56−{-# INLINE benchIdentitySink #-}
57−benchIdentitySink
58− :: (IsStream t, NFData b)
59− => Int -> String -> (t Identity Int -> Identity b) -> Benchmark
60−benchIdentitySink value name f = bench name $ nf (f . Ops.sourceUnfoldr value) 1
61−
62−-- | Takes a source, and uses it with a default drain/fold method.
63−{-# INLINE benchIOSrc #-}
64−benchIOSrc
65− :: (t IO a -> SerialT IO a)
66− -> String
67− -> (Int -> t IO a)
68− -> Benchmark
69−benchIOSrc t name f =
70− bench name $ nfIO $ randomRIO (1,1) >>= Ops.toNull t . f
71−
72−{-# INLINE benchPureSink #-}
73−benchPureSink :: NFData b => Int -> String -> (SerialT Identity Int -> b) -> Benchmark
74−benchPureSink value name f = benchPure name (Ops.sourceUnfoldr value) f
75−
76−benchIO :: (NFData b) => String -> (Int -> IO b) -> Benchmark
77−benchIO name f = bench name $ nfIO $ randomRIO (1,1) >>= f
78−
79−-------------------------------------------------------------------------------
80−--
81−-------------------------------------------------------------------------------
11+import Gauge
8212
8313-- In addition to gauge options, the number of elements in the stream can be
8414-- passed using the --stream-size option.
@@ -86,388 +16,42 @@ benchIO name f = bench name $ nfIO $ randomRIO (1,1) >>= f
8616main :: IO ()
8717main = do
8818 (value, cfg, benches) <- parseCLIOpts defaultStreamSize
89− value `seq` runMode (mode cfg) cfg benches
90− [ bgroup "serially"
91− [ bgroup "pure"
92− [ benchPureSink value "id" id
93− , benchPureSink1 "eqBy" (Ops.eqByPure value)
94− , benchPureSink value "==" Ops.eqInstance
95− , benchPureSink value "/=" Ops.eqInstanceNotEq
96− , benchPureSink1 "cmpBy" (Ops.cmpByPure value)
97− , benchPureSink value "<" Ops.ordInstance
98− , benchPureSink value "min" Ops.ordInstanceMin
99− , benchPureSrc "IsList.fromList" (Ops.sourceIsList value)
100− -- length is used to check for foldr/build fusion
101− , benchPureSink value "length . IsList.toList" (length . GHC.toList)
102− , benchPureSrc "IsString.fromString" (Ops.sourceIsString value)
103− , benchPureSink value "showsPrec pure streams" Ops.showInstance
104− , benchPureSink value "foldl'" Ops.pureFoldl'
105− ]
106− , bgroup "foldable"
107− [ -- Foldable instance
108− -- type class operations
109− bench "foldl'" $ nf (Ops.foldableFoldl' value) 1
110− , bench "foldrElem" $ nf (Ops.foldableFoldrElem value) 1
111− -- , bench "null" $ nf (Ops.foldableNull value) 1
112− , bench "elem" $ nf (Ops.foldableElem value) 1
113− , bench "length" $ nf (Ops.foldableLength value) 1
114− , bench "sum" $ nf (Ops.foldableSum value) 1
115− , bench "product" $ nf (Ops.foldableProduct value) 1
116− , bench "minimum" $ nf (Ops.foldableMin value) 1
117− , bench "maximum" $ nf (Ops.foldableMax value) 1
118− , bench "length . toList" $
119− nf (length . Ops.foldableToList value) 1
120−
121− -- folds
122− , bench "notElem" $ nf (Ops.foldableNotElem value) 1
123− , bench "find" $ nf (Ops.foldableFind value) 1
124− , bench "all" $ nf (Ops.foldableAll value) 1
125− , bench "any" $ nf (Ops.foldableAny value) 1
126− , bench "and" $ nf (Ops.foldableAnd value) 1
127− , bench "or" $ nf (Ops.foldableOr value) 1
128−
129− -- Note: minimumBy/maximumBy do not work in constant memory they are in
130− -- the O(n) group of benchmarks down below in this file.
131−
132− -- Applicative and Traversable operations
133− -- TBD: traverse_
134− , benchIOSink1 "mapM_" (Ops.foldableMapM_ value)
135− -- TBD: for_
136− -- TBD: forM_
137− , benchIOSink1 "sequence_" (Ops.foldableSequence_ value)
138− -- TBD: sequenceA_
139− -- TBD: asum
140− -- , benchIOSink1 "msum" (Ops.foldableMsum value)
141− ]
142− , bgroup "generation"
143− [ -- Most basic, barely stream continuations running
144− benchIOSrc serially "unfoldr" (Ops.sourceUnfoldr value)
145− , benchIOSrc serially "unfoldrM" (Ops.sourceUnfoldrM value)
146− , benchIOSrc serially "intFromTo" (Ops.sourceIntFromTo value)
147− , benchIOSrc serially "intFromThenTo" (Ops.sourceIntFromThenTo value)
148− , benchIOSrc serially "integerFromStep" (Ops.sourceIntegerFromStep value)
149− , benchIOSrc serially "fracFromThenTo" (Ops.sourceFracFromThenTo value)
150− , benchIOSrc serially "fracFromTo" (Ops.sourceFracFromTo value)
151− , benchIOSrc serially "fromList" (Ops.sourceFromList value)
152− , benchIOSrc serially "fromListM" (Ops.sourceFromListM value)
153− -- These are essentially cons and consM
154− , benchIOSrc serially "fromFoldable" (Ops.sourceFromFoldable value)
155− , benchIOSrc serially "fromFoldableM" (Ops.sourceFromFoldableM value)
156− , benchIOSrc serially "currentTime/0.00001s"
157− $ Ops.currentTime value 0.00001
158− ]
159− , bgroup "elimination"
160− [ bgroup "reduce"
161− [ bgroup "IO"
162− [
163− benchIOSink value "foldl'" Ops.foldl'Reduce
164− , benchIOSink value "foldl1'" Ops.foldl1'Reduce
165− , benchIOSink value "foldlM'" Ops.foldlM'Reduce
166− ]
167− , bgroup "Identity"
168− [
169− benchIdentitySink value "foldl'" Ops.foldl'Reduce
170− , benchIdentitySink value "foldl1'" Ops.foldl1'Reduce
171− , benchIdentitySink value "foldlM'" Ops.foldlM'Reduce
172− ]
173− ]
174−
175− , bgroup "build"
176− [ bgroup "IO"
177− [ benchIOSink value "foldrMElem" (Ops.foldrMElem value)
178− ]
179− , bgroup "Identity"
180− [ benchIdentitySink value "foldrMElem" (Ops.foldrMElem value)
181− , benchIdentitySink value "foldrMToStreamLength"
182− (S.length . runIdentity . Ops.foldrMToStream)
183− , benchPureSink value "foldrMToListLength"
184− (length . runIdentity . Ops.foldrMBuild)
185− ]
186− ]
187− , benchIOSink value "uncons" Ops.uncons
188− , benchIOSink value "toNull" $ Ops.toNull serially
189− , benchIOSink value "mapM_" Ops.mapM_
190−
191− , benchIOSink value "init" Ops.init
192−
193− -- this is too low and causes all benchmarks reported in ns
194− -- , benchIOSink value "head" Ops.head
195− , benchIOSink value "last" Ops.last
196− -- , benchIOSink value "lookup" Ops.lookup
197− , benchIOSink value "find" (Ops.find value)
198− , benchIOSink value "findIndex" (Ops.findIndex value)
199− , benchIOSink value "elemIndex" (Ops.elemIndex value)
200−
201− -- this is too low and causes all benchmarks reported in ns
202− -- , benchIOSink value "null" Ops.null
203− , benchIOSink value "elem" (Ops.elem value)
204− , benchIOSink value "notElem" (Ops.notElem value)
205− , benchIOSink value "all" (Ops.all value)
206− , benchIOSink value "any" (Ops.any value)
207− , benchIOSink value "and" (Ops.and value)
208− , benchIOSink value "or" (Ops.or value)
209−
210− , benchIOSink value "length" Ops.length
211− , benchHoistSink value "length . generally" (Ops.length . IP.generally)
212− , benchIOSink value "sum" Ops.sum
213− , benchIOSink value "product" Ops.product
214−
215− , benchIOSink value "maximumBy" Ops.maximumBy
216− , benchIOSink value "maximum" Ops.maximum
217− , benchIOSink value "minimumBy" Ops.minimumBy
218− , benchIOSink value "minimum" Ops.minimum
219−
220− ]
221− , bgroup "folds"
222− [ benchIOSink value "drain" (S.fold FL.drain)
223− , benchIOSink value "drainN" (S.fold (IFL.drainN value))
224− , benchIOSink value "drainWhileTrue" (S.fold (IFL.drainWhile $ (<=) (value + 1)))
225− , benchIOSink value "drainWhileFalse" (S.fold (IFL.drainWhile $ (>=) (value + 1)))
226− , benchIOSink value "sink" (S.fold $ Sink.toFold Sink.drain)
227− , benchIOSink value "last" (S.fold FL.last)
228− , benchIOSink value "lastN.1" (S.fold (IA.lastN 1))
229− , benchIOSink value "lastN.10" (S.fold (IA.lastN 10))
230− , benchIOSink value "length" (S.fold FL.length)
231− , benchIOSink value "sum" (S.fold FL.sum)
232− , benchIOSink value "product" (S.fold FL.product)
233− , benchIOSink value "maximumBy" (S.fold (FL.maximumBy compare))
234− , benchIOSink value "maximum" (S.fold FL.maximum)
235− , benchIOSink value "minimumBy" (S.fold (FL.minimumBy compare))
236− , benchIOSink value "minimum" (S.fold FL.minimum)
237− , benchIOSink value "mean" (\s -> S.fold FL.mean (S.map (fromIntegral :: Int -> Double) s))
238− , benchIOSink value "variance" (\s -> S.fold FL.variance (S.map (fromIntegral :: Int -> Double) s))
239− , benchIOSink value "stdDev" (\s -> S.fold FL.stdDev (S.map (fromIntegral :: Int -> Double) s))
240−
241− , benchIOSink value "mconcat" (S.fold FL.mconcat . (S.map (Last . Just)))
242− , benchIOSink value "foldMap" (S.fold (FL.foldMap (Last . Just)))
243−
244− , benchIOSink value "index" (S.fold (FL.index (value + 1)))
245− , benchIOSink value "head" (S.fold FL.head)
246− , benchIOSink value "find" (S.fold (FL.find (== (value + 1))))
247− , benchIOSink value "findIndex" (S.fold (FL.findIndex (== (value + 1))))
248− , benchIOSink value "elemIndex" (S.fold (FL.elemIndex (value + 1)))
249−
250− , benchIOSink value "null" (S.fold FL.null)
251− , benchIOSink value "elem" (S.fold (FL.elem (value + 1)))
252− , benchIOSink value "notElem" (S.fold (FL.notElem (value + 1)))
253− , benchIOSink value "all" (S.fold (FL.all (<= (value + 1))))
254− , benchIOSink value "any" (S.fold (FL.any (> (value + 1))))
255− , benchIOSink value "and" (\s -> S.fold FL.and (S.map (<= (value + 1)) s))
256− , benchIOSink value "or" (\s -> S.fold FL.or (S.map (> (value + 1)) s))
257− ]
258− , bgroup "fold-multi-stream"
259− [ benchIOSink1 "eqBy" (Ops.eqBy value)
260− , benchIOSink1 "cmpBy" (Ops.cmpBy value)
261− , benchIOSink value "isPrefixOf" Ops.isPrefixOf
262− , benchIOSink value "isSubsequenceOf" Ops.isSubsequenceOf
263− , benchIOSink value "stripPrefix" Ops.stripPrefix
264− ]
265− , bgroup "folds-transforms"
266− [ benchIOSink value "drain" (S.fold FL.drain)
267− , benchIOSink value "lmap" (S.fold (IFL.lmap (+1) FL.drain))
268− , benchIOSink value "pipe-mapM"
269− (S.fold (IFL.transform (Pipe.mapM (\x -> return $ x + 1)) FL.drain))
270− ]
271− , bgroup "folds-compositions" -- Applicative
272− [
273− benchIOSink value "all,any" (S.fold ((,) <$> FL.all (<= (value + 1))
274− <*> FL.any (> (value + 1))))
275− , benchIOSink value "sum,length" (S.fold ((,) <$> FL.sum <*> FL.length))
276− ]
277− , bgroup "pipes"
278− [ benchIOSink value "mapM" (Ops.transformMapM serially 1)
279− , benchIOSink value "compose" (Ops.transformComposeMapM serially 1)
280− , benchIOSink value "tee" (Ops.transformTeeMapM serially 1)
281− , benchIOSink value "zip" (Ops.transformZipMapM serially 1)
282− ]
283− , bgroup "pipesX4"
284− [ benchIOSink value "mapM" (Ops.transformMapM serially 4)
285− , benchIOSink value "compose" (Ops.transformComposeMapM serially 4)
286− , benchIOSink value "tee" (Ops.transformTeeMapM serially 4)
287− , benchIOSink value "zip" (Ops.transformZipMapM serially 4)
288− ]
289− , bgroup "transformer"
290− [ benchIOSrc serially "evalState" (Ops.evalStateT value)
291− , benchIOSrc serially "withState" (Ops.withState value)
292− ]
293− , bgroup "transformation"
294− [ benchIOSink value "scanl" (Ops.scan 1)
295− , benchIOSink value "scanl1'" (Ops.scanl1' 1)
296− , benchIOSink value "map" (Ops.map 1)
297− , benchIOSink value "fmap" (Ops.fmap 1)
298− , benchIOSink value "mapM" (Ops.mapM serially 1)
299− , benchIOSink value "mapMaybe" (Ops.mapMaybe 1)
300− , benchIOSink value "mapMaybeM" (Ops.mapMaybeM 1)
301− , bench "sequence" $ nfIO $ randomRIO (1,1000) >>= \n ->
302− Ops.sequence serially (Ops.sourceUnfoldrMAction value n)
303− , benchIOSink value "findIndices" (Ops.findIndices value 1)
304− , benchIOSink value "elemIndices" (Ops.elemIndices value 1)
305− , benchIOSink value "foldrS" (Ops.foldrS 1)
306− , benchIOSink value "foldrSMap" (Ops.foldrSMap 1)
307− , benchIOSink value "foldrT" (Ops.foldrT 1)
308− , benchIOSink value "foldrTMap" (Ops.foldrTMap 1)
309− , benchIOSink value "tap" (Ops.tap 1)
310− , benchIOSink value "tapRate 1 second" (Ops.tapRate 1)
311− , benchIOSink value "pollCounts 1 second" (Ops.pollCounts 1)
312− , benchIOSink value "tapAsync" (Ops.tapAsync 1)
313− , benchIOSink value "tapAsyncS" (Ops.tapAsyncS 1)
314− ]
315− , bgroup "transformationX4"
316− [ benchIOSink value "scan" (Ops.scan 4)
317− , benchIOSink value "scanl1'" (Ops.scanl1' 4)
318− , benchIOSink value "map" (Ops.map 4)
319− , benchIOSink value "fmap" (Ops.fmap 4)
320− , benchIOSink value "mapM" (Ops.mapM serially 4)
321− , benchIOSink value "mapMaybe" (Ops.mapMaybe 4)
322− , benchIOSink value "mapMaybeM" (Ops.mapMaybeM 4)
323− -- , bench "sequence" $ nfIO $ randomRIO (1,1000) >>= \n ->
324− -- Ops.sequence serially (Ops.sourceUnfoldrMAction n)
325− , benchIOSink value "findIndices" (Ops.findIndices value 4)
326− , benchIOSink value "elemIndices" (Ops.elemIndices value 4)
327− ]
328− , bgroup "filtering"
329− [ benchIOSink value "filter-even" (Ops.filterEven 1)
330− , benchIOSink value "filter-all-out" (Ops.filterAllOut value 1)
331− , benchIOSink value "filter-all-in" (Ops.filterAllIn value 1)
332−
333− , benchIOSink value "take-all" (Ops.takeAll value 1)
334− , benchIOSink value "takeByTime-all"
335− (Ops.takeByTime (NanoSecond64 maxBound) 1)
336− , benchIOSink value "takeWhile-true" (Ops.takeWhileTrue value 1)
337− --, benchIOSink value "takeWhileM-true" (Ops.takeWhileMTrue 1)
338−
339− -- "drop-one" is dual to "last"
340− , benchIOSink value "drop-one" (Ops.dropOne 1)
341− , benchIOSink value "drop-all" (Ops.dropAll value 1)
342− , benchIOSink value "dropByTime-all"
343− (Ops.dropByTime (NanoSecond64 maxBound) 1)
344− , benchIOSink value "dropWhile-true" (Ops.dropWhileTrue value 1)
345− --, benchIOSink value "dropWhileM-true" (Ops.dropWhileMTrue 1)
346− , benchIOSink value "dropWhile-false" (Ops.dropWhileFalse value 1)
347−
348− , benchIOSink value "deleteBy" (Ops.deleteBy value 1)
349− , benchIOSink value "intersperse" (Ops.intersperse value 1)
350− , benchIOSink value "insertBy" (Ops.insertBy value 1)
351− ]
352− , bgroup "filteringX4"
353− [ benchIOSink value "filter-even" (Ops.filterEven 4)
354− , benchIOSink value "filter-all-out" (Ops.filterAllOut value 4)
355− , benchIOSink value "filter-all-in" (Ops.filterAllIn value 4)
356− , benchIOSink value "take-all" (Ops.takeAll value 4)
357− , benchIOSink value "takeWhile-true" (Ops.takeWhileTrue value 4)
358− --, benchIOSink value "takeWhileM-true" (Ops.takeWhileMTrue 4)
359− , benchIOSink value "drop-one" (Ops.dropOne 4)
360− , benchIOSink value "drop-all" (Ops.dropAll value 4)
361− , benchIOSink value "dropWhile-true" (Ops.dropWhileTrue value 4)
362− --, benchIOSink value "dropWhileM-true" (Ops.dropWhileMTrue 4)
363− , benchIOSink value "dropWhile-false" (Ops.dropWhileFalse value 4)
364− , benchIOSink value "deleteBy" (Ops.deleteBy value 4)
365− , benchIOSink value "intersperse" (Ops.intersperse value 4)
366− , benchIOSink value "insertBy" (Ops.insertBy value 4)
367− ]
368− , bgroup "joining"
369− [ benchIOSrc1 "zip (2,x/2)" (Ops.zip (value `div` 2))
370− , benchIOSrc1 "zipM (2,x/2)" (Ops.zipM (value `div` 2))
371− , benchIOSrc1 "mergeBy (2,x/2)" (Ops.mergeBy (value `div` 2))
372− , benchIOSrc1 "serial (2,x/2)" (Ops.serial2 (value `div` 2))
373− , benchIOSrc1 "append (2,x/2)" (Ops.append2 (value `div` 2))
374− , benchIOSrc1 "serial (2,2,x/4)" (Ops.serial4 (value `div` 4))
375− , benchIOSrc1 "append (2,2,x/4)" (Ops.append4 (value `div` 4))
376− , benchIOSrc1 "wSerial (2,x/2)" (Ops.wSerial2 value)
377− , benchIOSrc1 "interleave (2,x/2)" (Ops.interleave2 value)
378− , benchIOSrc1 "roundRobin (2,x/2)" (Ops.roundRobin2 value)
379− ]
380− , bgroup "concat-foldable"
381− [ benchIOSrc serially "foldMapWith" (Ops.sourceFoldMapWith value)
382− , benchIOSrc serially "foldMapWithM" (Ops.sourceFoldMapWithM value)
383− , benchIOSrc serially "foldMapM" (Ops.sourceFoldMapM value)
384− , benchIOSrc serially "foldWithConcatMapId" (Ops.sourceConcatMapId value)
385− ]
386− , bgroup "concat-serial"
387− [ benchIOSrc1 "concatMapPure (2,x/2)" (Ops.concatMapPure 2 (value `div` 2))
388− , benchIOSrc1 "concatMap (2,x/2)" (Ops.concatMap 2 (value `div` 2))
389− , benchIOSrc1 "concatMap (x/2,2)" (Ops.concatMap (value `div` 2) 2)
390− , benchIOSrc1 "concatMapRepl (x/4,4)" (Ops.concatMapRepl4xN value)
391− , benchIOSrc1 "concatUnfoldRepl (x/4,4)" (Ops.concatUnfoldRepl4xN value)
392−
393− , benchIOSrc1 "concatMapWithSerial (2,x/2)"
394− (Ops.concatMapWithSerial 2 (value `div` 2))
395− , benchIOSrc1 "concatMapWithSerial (x/2,2)"
396− (Ops.concatMapWithSerial (value `div` 2) 2)
397−
398− , benchIOSrc1 "concatMapWithAppend (2,x/2)"
399− (Ops.concatMapWithAppend 2 (value `div` 2))
400− ]
401− , bgroup "outer-product-streams"
402− [ benchIO "toNullAp" $ Nested.toNullAp value serially
403− , benchIO "toNull" $ Nested.toNull value serially
404− , benchIO "toNull3" $ Nested.toNull3 value serially
405− , benchIO "filterAllOut" $ Nested.filterAllOut value serially
406− , benchIO "filterAllIn" $ Nested.filterAllIn value serially
407− , benchIO "filterSome" $ Nested.filterSome value serially
408− , benchIO "breakAfterSome" $ Nested.breakAfterSome value serially
409− ]
410− , bgroup "outer-product-unfolds"
411− [ benchIO "toNull" $ NestedUnfold.toNull value
412− , benchIO "toNull3" $ NestedUnfold.toNull3 value
413− , benchIO "concat" $ NestedUnfold.concat value
414− , benchIO "filterAllOut" $ NestedUnfold.filterAllOut value
415− , benchIO "filterAllIn" $ NestedUnfold.filterAllIn value
416− , benchIO "filterSome" $ NestedUnfold.filterSome value
417− , benchIO "breakAfterSome" $ NestedUnfold.breakAfterSome value
418− ]
419− -- scanl-map and foldl-map are equivalent to the scan and fold in the foldl
420− -- library. If scan/fold followed by a map is efficient enough we may not
421− -- need monolithic implementations of these.
422− , bgroup "mixed"
423− [ benchIOSink value "scanl-map" (Ops.scanMap 1)
424− , benchIOSink value "foldl-map" Ops.foldl'ReduceMap
425− , benchIOSink value "sum-product-fold" Ops.sumProductFold
426− , benchIOSink value "sum-product-scan" Ops.sumProductScan
427− ]
428− , bgroup "mixedX4"
429− [ benchIOSink value "scan-map" (Ops.scanMap 4)
430− , benchIOSink value "drop-map" (Ops.dropMap 4)
431− , benchIOSink value "drop-scan" (Ops.dropScan 4)
432− , benchIOSink value "take-drop" (Ops.takeDrop value 4)
433− , benchIOSink value "take-scan" (Ops.takeScan value 4)
434− , benchIOSink value "take-map" (Ops.takeMap value 4)
435− , benchIOSink value "filter-drop" (Ops.filterDrop value 4)
436− , benchIOSink value "filter-take" (Ops.filterTake value 4)
437− , benchIOSink value "filter-scan" (Ops.filterScan 4)
438− , benchIOSink value "filter-scanl1" (Ops.filterScanl1 4)
439− , benchIOSink value "filter-map" (Ops.filterMap value 4)
440− ]
441− ]
442− , bgroup "wSerially"
443− [ bgroup "transformation"
444− [ benchIOSink value "fmap" $ Ops.fmap' wSerially 1
445− ]
446− , bgroup "concatMap"
447− [ benchIOSrc1 "concatMapWithWSerial (2,x/2)"
448− (Ops.concatMapWithWSerial 2 (value `div` 2))
449− , benchIOSrc1 "concatMapWithWSerial (x/2,2)"
450− (Ops.concatMapWithWSerial (value `div` 2) 2)
451− ]
452− , bgroup "outer-product"
453− [ benchIO "toNullAp" $ Nested.toNullAp value wSerially
454− , benchIO "toNull" $ Nested.toNull value wSerially
455− , benchIO "toNull3" $ Nested.toNull3 value wSerially
456− , benchIO "filterAllOut" $ Nested.filterAllOut value wSerially
457− , benchIO "filterAllIn" $ Nested.filterAllIn value wSerially
458− , benchIO "filterSome" $ Nested.filterSome value wSerially
459− , benchIO "breakAfterSome" $ Nested.breakAfterSome value wSerially
460− ]
461− ]
462− , bgroup "zipSerially"
463− [ bgroup "transformation"
464− [ benchIOSink value "fmap" $ Ops.fmap' zipSerially 1
465− ]
466− -- XXX needs fixing
467− {-
468− , bgroup "outer-product"
469− [ benchIO "toNullAp" $ Nested.toNullAp value zipSerially
470− ]
471− -}
472− ]
473− ]
19+ value `seq`
20+ runMode
21+ (mode cfg)
22+ cfg
23+ benches
24+ (concat [serial value, wSerial value, zipSerial value])
25+ where
26+ serial value =
27+ concat
28+ [ o_1_space_serial_pure value
29+ , o_1_space_serial_foldable value
30+ , o_1_space_serial_generation value
31+ , o_1_space_serial_elimination value
32+ , o_1_space_serial_folds value
33+ , o_1_space_serial_foldMultiStream value
34+ , o_1_space_serial_foldsTransforms value
35+ , o_1_space_serial_foldsCompositions value
36+ , o_1_space_serial_pipes value
37+ , o_1_space_serial_pipesX4 value
38+ , o_1_space_serial_transformer value
39+ , o_1_space_serial_transformation value
40+ , o_1_space_serial_transformationX4 value
41+ , o_1_space_serial_filtering value
42+ , o_1_space_serial_filteringX4 value
43+ , o_1_space_serial_joining value
44+ , o_1_space_serial_concatFoldable value
45+ , o_1_space_serial_concatSerial value
46+ , o_1_space_serial_outerProductStreams value
47+ , o_1_space_serial_outerProductUnfolds value
48+ , o_1_space_serial_mixed value
49+ , o_1_space_serial_mixedX4 value
50+ ]
51+ wSerial value =
52+ concat
53+ [ o_1_space_wSerial_transformation value
54+ , o_1_space_wSerial_concatMap value
55+ , o_1_space_wSerial_outerProduct value
56+ ]
57+ zipSerial value = concat [o_1_space_zipSerial_transformation value]
benchmark/lib/Streamly/Benchmark/Groups.hsnew file+792
@@ -0,0 +1,792 @@
1+-- |
2+-- Module : Main
3+-- Copyright : (c) 2018 Harendra Kumar
4+--
5+-- License : BSD3
6+-- Maintainer : streamly@composewell.com
7+
8+module Streamly.Benchmark.Groups where
9+
10+import Control.DeepSeq (NFData(..))
11+import Data.Functor.Identity (Identity, runIdentity)
12+import Data.Monoid (Last(..))
13+import System.Random (randomRIO)
14+
15+import qualified GHC.Exts as GHC
16+import qualified Streamly.Benchmark.Prelude as Ops
17+
18+import Streamly
19+import qualified Streamly.Data.Fold as FL
20+import qualified Streamly.Prelude as S
21+import qualified Streamly.Internal.Data.Sink as Sink
22+
23+import Streamly.Internal.Data.Time.Units
24+import qualified Streamly.Internal.Memory.Array as IA
25+import qualified Streamly.Internal.Data.Fold as IFL
26+import qualified Streamly.Internal.Prelude as IP
27+import qualified Streamly.Internal.Data.Pipe as Pipe
28+
29+import qualified NestedOps as Nested
30+import qualified NestedUnfoldOps as NestedUnfold
31+
32+import Gauge
33+import Streamly.Benchmark.Common
34+
35+-------------------------------------------------------------------------------
36+--
37+-------------------------------------------------------------------------------
38+
39+-- We need a monadic bind here to make sure that the function f does not get
40+-- completely optimized out by the compiler in some cases.
41+
42+-- | Takes a fold method, and uses it with a default source.
43+{-# INLINE benchIOSink #-}
44+benchIOSink
45+ :: (IsStream t, NFData b)
46+ => Int -> String -> (t IO Int -> IO b) -> Benchmark
47+benchIOSink value name f = bench name $ nfIO $ randomRIO (1,1) >>= f . Ops.source value
48+
49+{-# INLINE benchHoistSink #-}
50+benchHoistSink
51+ :: (IsStream t, NFData b)
52+ => Int -> String -> (t Identity Int -> IO b) -> Benchmark
53+benchHoistSink value name f =
54+ bench name $ nfIO $ randomRIO (1,1) >>= f . Ops.sourceUnfoldr value
55+
56+-- XXX We should be using sourceUnfoldrM for fair comparison with IO monad, but
57+-- we can't use it as it requires MonadAsync constraint.
58+{-# INLINE benchIdentitySink #-}
59+benchIdentitySink
60+ :: (IsStream t, NFData b)
61+ => Int -> String -> (t Identity Int -> Identity b) -> Benchmark
62+benchIdentitySink value name f = bench name $ nf (f . Ops.sourceUnfoldr value) 1
63+
64+-- | Takes a source, and uses it with a default drain/fold method.
65+{-# INLINE benchIOSrc #-}
66+benchIOSrc
67+ :: (t IO a -> SerialT IO a)
68+ -> String
69+ -> (Int -> t IO a)
70+ -> Benchmark
71+benchIOSrc t name f =
72+ bench name $ nfIO $ randomRIO (1,1) >>= Ops.toNull t . f
73+
74+{-# INLINE benchPureSink #-}
75+benchPureSink :: NFData b => Int -> String -> (SerialT Identity Int -> b) -> Benchmark
76+benchPureSink value name f = benchPure name (Ops.sourceUnfoldr value) f
77+
78+benchIO :: (NFData b) => String -> (Int -> IO b) -> Benchmark
79+benchIO name f = bench name $ nfIO $ randomRIO (1,1) >>= f
80+
81+-------------------------------------------------------------------------------
82+-- Serial : O(1) Space
83+-------------------------------------------------------------------------------
84+
85+o_1_space_serial_pure :: Int -> [Benchmark]
86+o_1_space_serial_pure value =
87+ [ bgroup
88+ "serially"
89+ [ bgroup
90+ "pure"
91+ [ benchPureSink value "id" id
92+ , benchPureSink1 "eqBy" (Ops.eqByPure value)
93+ , benchPureSink value "==" Ops.eqInstance
94+ , benchPureSink value "/=" Ops.eqInstanceNotEq
95+ , benchPureSink1 "cmpBy" (Ops.cmpByPure value)
96+ , benchPureSink value "<" Ops.ordInstance
97+ , benchPureSink value "min" Ops.ordInstanceMin
98+ , benchPureSrc "IsList.fromList" (Ops.sourceIsList value)
99+ -- length is used to check for foldr/build fusion
100+ , benchPureSink
101+ value
102+ "length . IsList.toList"
103+ (length . GHC.toList)
104+ , benchPureSrc "IsString.fromString" (Ops.sourceIsString value)
105+ , benchPureSink value "showsPrec pure streams" Ops.showInstance
106+ , benchPureSink value "foldl'" Ops.pureFoldl'
107+ ]
108+ ]
109+ ]
110+
111+o_1_space_serial_foldable :: Int -> [Benchmark]
112+o_1_space_serial_foldable value =
113+ [ bgroup
114+ "serially"
115+ [ bgroup
116+ "foldable"
117+ -- Foldable instance
118+ -- type class operations
119+ [ bench "foldl'" $ nf (Ops.foldableFoldl' value) 1
120+ , bench "foldrElem" $ nf (Ops.foldableFoldrElem value) 1
121+ -- , bench "null" $ nf (Ops.foldableNull value) 1
122+ , bench "elem" $ nf (Ops.foldableElem value) 1
123+ , bench "length" $ nf (Ops.foldableLength value) 1
124+ , bench "sum" $ nf (Ops.foldableSum value) 1
125+ , bench "product" $ nf (Ops.foldableProduct value) 1
126+ , bench "minimum" $ nf (Ops.foldableMin value) 1
127+ , bench "maximum" $ nf (Ops.foldableMax value) 1
128+ , bench "length . toList" $
129+ nf (length . Ops.foldableToList value) 1
130+ -- folds
131+ , bench "notElem" $ nf (Ops.foldableNotElem value) 1
132+ , bench "find" $ nf (Ops.foldableFind value) 1
133+ , bench "all" $ nf (Ops.foldableAll value) 1
134+ , bench "any" $ nf (Ops.foldableAny value) 1
135+ , bench "and" $ nf (Ops.foldableAnd value) 1
136+ , bench "or" $ nf (Ops.foldableOr value) 1
137+ -- Note: minimumBy/maximumBy do not work in constant memory they are in
138+ -- the O(n) group of benchmarks down below in this file.
139+ -- Applicative and Traversable operations
140+ -- TBD: traverse_
141+ , benchIOSink1 "mapM_" (Ops.foldableMapM_ value)
142+ -- TBD: for_
143+ -- TBD: forM_
144+ , benchIOSink1 "sequence_" (Ops.foldableSequence_ value)
145+ -- TBD: sequenceA_
146+ -- TBD: asum
147+ -- , benchIOSink1 "msum" (Ops.foldableMsum value)
148+ ]
149+ ]
150+ ]
151+
152+o_1_space_serial_generation :: Int -> [Benchmark]
153+o_1_space_serial_generation value =
154+ [ bgroup
155+ "serially"
156+ [ bgroup
157+ "generation"
158+ -- Most basic, barely stream continuations running
159+ [ benchIOSrc serially "unfoldr" (Ops.sourceUnfoldr value)
160+ , benchIOSrc serially "unfoldrM" (Ops.sourceUnfoldrM value)
161+ , benchIOSrc serially "intFromTo" (Ops.sourceIntFromTo value)
162+ , benchIOSrc
163+ serially
164+ "intFromThenTo"
165+ (Ops.sourceIntFromThenTo value)
166+ , benchIOSrc
167+ serially
168+ "integerFromStep"
169+ (Ops.sourceIntegerFromStep value)
170+ , benchIOSrc
171+ serially
172+ "fracFromThenTo"
173+ (Ops.sourceFracFromThenTo value)
174+ , benchIOSrc serially "fracFromTo" (Ops.sourceFracFromTo value)
175+ , benchIOSrc serially "fromList" (Ops.sourceFromList value)
176+ , benchIOSrc serially "fromListM" (Ops.sourceFromListM value)
177+ -- These are essentially cons and consM
178+ , benchIOSrc
179+ serially
180+ "fromFoldable"
181+ (Ops.sourceFromFoldable value)
182+ , benchIOSrc
183+ serially
184+ "fromFoldableM"
185+ (Ops.sourceFromFoldableM value)
186+ , benchIOSrc serially "currentTime/0.00001s" $
187+ Ops.currentTime value 0.00001
188+ ]
189+ ]
190+ ]
191+
192+o_1_space_serial_elimination :: Int -> [Benchmark]
193+o_1_space_serial_elimination value =
194+ [ bgroup
195+ "serially"
196+ [ bgroup
197+ "elimination"
198+ [ bgroup
199+ "reduce"
200+ [ bgroup
201+ "IO"
202+ [ benchIOSink value "foldl'" Ops.foldl'Reduce
203+ , benchIOSink value "foldl1'" Ops.foldl1'Reduce
204+ , benchIOSink value "foldlM'" Ops.foldlM'Reduce
205+ ]
206+ , bgroup
207+ "Identity"
208+ [ benchIdentitySink value "foldl'" Ops.foldl'Reduce
209+ , benchIdentitySink
210+ value
211+ "foldl1'"
212+ Ops.foldl1'Reduce
213+ , benchIdentitySink
214+ value
215+ "foldlM'"
216+ Ops.foldlM'Reduce
217+ ]
218+ ]
219+ , bgroup
220+ "build"
221+ [ bgroup
222+ "IO"
223+ [ benchIOSink
224+ value
225+ "foldrMElem"
226+ (Ops.foldrMElem value)
227+ ]
228+ , bgroup
229+ "Identity"
230+ [ benchIdentitySink
231+ value
232+ "foldrMElem"
233+ (Ops.foldrMElem value)
234+ , benchIdentitySink
235+ value
236+ "foldrMToStreamLength"
237+ (S.length . runIdentity . Ops.foldrMToStream)
238+ , benchPureSink
239+ value
240+ "foldrMToListLength"
241+ (length . runIdentity . Ops.foldrMBuild)
242+ ]
243+ ]
244+ , benchIOSink value "uncons" Ops.uncons
245+ , benchIOSink value "toNull" $ Ops.toNull serially
246+ , benchIOSink value "mapM_" Ops.mapM_
247+ , benchIOSink value "init" Ops.init
248+ -- this is too low and causes all benchmarks reported in ns
249+ -- , benchIOSink value "head" Ops.head
250+ , benchIOSink value "last" Ops.last
251+ -- , benchIOSink value "lookup" Ops.lookup
252+ , benchIOSink value "find" (Ops.find value)
253+ , benchIOSink value "findIndex" (Ops.findIndex value)
254+ , benchIOSink value "elemIndex" (Ops.elemIndex value)
255+ -- this is too low and causes all benchmarks reported in ns
256+ -- , benchIOSink value "null" Ops.null
257+ , benchIOSink value "elem" (Ops.elem value)
258+ , benchIOSink value "notElem" (Ops.notElem value)
259+ , benchIOSink value "all" (Ops.all value)
260+ , benchIOSink value "any" (Ops.any value)
261+ , benchIOSink value "and" (Ops.and value)
262+ , benchIOSink value "or" (Ops.or value)
263+ , benchIOSink value "length" Ops.length
264+ , benchHoistSink
265+ value
266+ "length . generally"
267+ (Ops.length . IP.generally)
268+ , benchIOSink value "sum" Ops.sum
269+ , benchIOSink value "product" Ops.product
270+ , benchIOSink value "maximumBy" Ops.maximumBy
271+ , benchIOSink value "maximum" Ops.maximum
272+ , benchIOSink value "minimumBy" Ops.minimumBy
273+ , benchIOSink value "minimum" Ops.minimum
274+ ]
275+ ]
276+ ]
277+
278+o_1_space_serial_folds :: Int -> [Benchmark]
279+o_1_space_serial_folds value =
280+ [ bgroup
281+ "serially"
282+ [ bgroup
283+ "folds"
284+ [ benchIOSink value "drain" (S.fold FL.drain)
285+ , benchIOSink value "drainN" (S.fold (IFL.drainN value))
286+ , benchIOSink
287+ value
288+ "drainWhileTrue"
289+ (S.fold (IFL.drainWhile $ (<=) (value + 1)))
290+ , benchIOSink
291+ value
292+ "drainWhileFalse"
293+ (S.fold (IFL.drainWhile $ (>=) (value + 1)))
294+ , benchIOSink value "sink" (S.fold $ Sink.toFold Sink.drain)
295+ , benchIOSink value "last" (S.fold FL.last)
296+ , benchIOSink value "lastN.1" (S.fold (IA.lastN 1))
297+ , benchIOSink value "lastN.10" (S.fold (IA.lastN 10))
298+ , benchIOSink value "length" (S.fold FL.length)
299+ , benchIOSink value "sum" (S.fold FL.sum)
300+ , benchIOSink value "product" (S.fold FL.product)
301+ , benchIOSink value "maximumBy" (S.fold (FL.maximumBy compare))
302+ , benchIOSink value "maximum" (S.fold FL.maximum)
303+ , benchIOSink value "minimumBy" (S.fold (FL.minimumBy compare))
304+ , benchIOSink value "minimum" (S.fold FL.minimum)
305+ , benchIOSink
306+ value
307+ "mean"
308+ (\s ->
309+ S.fold
310+ FL.mean
311+ (S.map (fromIntegral :: Int -> Double) s))
312+ , benchIOSink
313+ value
314+ "variance"
315+ (\s ->
316+ S.fold
317+ FL.variance
318+ (S.map (fromIntegral :: Int -> Double) s))
319+ , benchIOSink
320+ value
321+ "stdDev"
322+ (\s ->
323+ S.fold
324+ FL.stdDev
325+ (S.map (fromIntegral :: Int -> Double) s))
326+ , benchIOSink
327+ value
328+ "mconcat"
329+ (S.fold FL.mconcat . (S.map (Last . Just)))
330+ , benchIOSink
331+ value
332+ "foldMap"
333+ (S.fold (FL.foldMap (Last . Just)))
334+ , benchIOSink value "index" (S.fold (FL.index (value + 1)))
335+ , benchIOSink value "head" (S.fold FL.head)
336+ , benchIOSink value "find" (S.fold (FL.find (== (value + 1))))
337+ , benchIOSink
338+ value
339+ "findIndex"
340+ (S.fold (FL.findIndex (== (value + 1))))
341+ , benchIOSink
342+ value
343+ "elemIndex"
344+ (S.fold (FL.elemIndex (value + 1)))
345+ , benchIOSink value "null" (S.fold FL.null)
346+ , benchIOSink value "elem" (S.fold (FL.elem (value + 1)))
347+ , benchIOSink value "notElem" (S.fold (FL.notElem (value + 1)))
348+ , benchIOSink value "all" (S.fold (FL.all (<= (value + 1))))
349+ , benchIOSink value "any" (S.fold (FL.any (> (value + 1))))
350+ , benchIOSink
351+ value
352+ "and"
353+ (\s -> S.fold FL.and (S.map (<= (value + 1)) s))
354+ , benchIOSink
355+ value
356+ "or"
357+ (\s -> S.fold FL.or (S.map (> (value + 1)) s))
358+ ]
359+ ]
360+ ]
361+
362+o_1_space_serial_foldMultiStream :: Int -> [Benchmark]
363+o_1_space_serial_foldMultiStream value =
364+ [ bgroup
365+ "serially"
366+ [ bgroup
367+ "fold-multi-stream"
368+ [ benchIOSink1 "eqBy" (Ops.eqBy value)
369+ , benchIOSink1 "cmpBy" (Ops.cmpBy value)
370+ , benchIOSink value "isPrefixOf" Ops.isPrefixOf
371+ , benchIOSink value "isSubsequenceOf" Ops.isSubsequenceOf
372+ , benchIOSink value "stripPrefix" Ops.stripPrefix
373+ ]
374+ ]
375+ ]
376+
377+o_1_space_serial_foldsTransforms :: Int -> [Benchmark]
378+o_1_space_serial_foldsTransforms value =
379+ [ bgroup
380+ "serially"
381+ [ bgroup
382+ "folds-transforms"
383+ [ benchIOSink value "drain" (S.fold FL.drain)
384+ , benchIOSink value "lmap" (S.fold (IFL.lmap (+ 1) FL.drain))
385+ , benchIOSink
386+ value
387+ "pipe-mapM"
388+ (S.fold
389+ (IFL.transform
390+ (Pipe.mapM (\x -> return $ x + 1))
391+ FL.drain))
392+ ]
393+ ]
394+ ]
395+
396+o_1_space_serial_foldsCompositions :: Int -> [Benchmark]
397+o_1_space_serial_foldsCompositions value =
398+ [ bgroup
399+ "serially"
400+ [ bgroup
401+ "folds-compositions" -- Applicative
402+ [ benchIOSink
403+ value
404+ "all,any"
405+ (S.fold
406+ ((,) <$> FL.all (<= (value + 1)) <*>
407+ FL.any (> (value + 1))))
408+ , benchIOSink
409+ value
410+ "sum,length"
411+ (S.fold ((,) <$> FL.sum <*> FL.length))
412+ ]
413+ ]
414+ ]
415+
416+o_1_space_serial_pipes :: Int -> [Benchmark]
417+o_1_space_serial_pipes value =
418+ [ bgroup
419+ "serially"
420+ [ bgroup
421+ "pipes"
422+ [ benchIOSink value "mapM" (Ops.transformMapM serially 1)
423+ , benchIOSink
424+ value
425+ "compose"
426+ (Ops.transformComposeMapM serially 1)
427+ , benchIOSink value "tee" (Ops.transformTeeMapM serially 1)
428+ , benchIOSink value "zip" (Ops.transformZipMapM serially 1)
429+ ]
430+ ]
431+ ]
432+
433+o_1_space_serial_pipesX4 :: Int -> [Benchmark]
434+o_1_space_serial_pipesX4 value =
435+ [ bgroup
436+ "serially"
437+ [ bgroup
438+ "pipesX4"
439+ [ benchIOSink value "mapM" (Ops.transformMapM serially 4)
440+ , benchIOSink
441+ value
442+ "compose"
443+ (Ops.transformComposeMapM serially 4)
444+ , benchIOSink value "tee" (Ops.transformTeeMapM serially 4)
445+ , benchIOSink value "zip" (Ops.transformZipMapM serially 4)
446+ ]
447+ ]
448+ ]
449+
450+
451+o_1_space_serial_transformer :: Int -> [Benchmark]
452+o_1_space_serial_transformer value =
453+ [ bgroup
454+ "serially"
455+ [ bgroup
456+ "transformer"
457+ [ benchIOSrc serially "evalState" (Ops.evalStateT value)
458+ , benchIOSrc serially "withState" (Ops.withState value)
459+ ]
460+ ]
461+ ]
462+
463+o_1_space_serial_transformation :: Int -> [Benchmark]
464+o_1_space_serial_transformation value =
465+ [ bgroup
466+ "serially"
467+ [ bgroup
468+ "transformation"
469+ [ benchIOSink value "scanl" (Ops.scan 1)
470+ , benchIOSink value "scanl1'" (Ops.scanl1' 1)
471+ , benchIOSink value "map" (Ops.map 1)
472+ , benchIOSink value "fmap" (Ops.fmap 1)
473+ , benchIOSink value "mapM" (Ops.mapM serially 1)
474+ , benchIOSink value "mapMaybe" (Ops.mapMaybe 1)
475+ , benchIOSink value "mapMaybeM" (Ops.mapMaybeM 1)
476+ , bench "sequence" $
477+ nfIO $
478+ randomRIO (1, 1000) >>= \n ->
479+ Ops.sequence serially (Ops.sourceUnfoldrMAction value n)
480+ , benchIOSink value "findIndices" (Ops.findIndices value 1)
481+ , benchIOSink value "elemIndices" (Ops.elemIndices value 1)
482+ , benchIOSink value "foldrS" (Ops.foldrS 1)
483+ , benchIOSink value "foldrSMap" (Ops.foldrSMap 1)
484+ , benchIOSink value "foldrT" (Ops.foldrT 1)
485+ , benchIOSink value "foldrTMap" (Ops.foldrTMap 1)
486+ , benchIOSink value "tap" (Ops.tap 1)
487+ , benchIOSink value "tapRate 1 second" (Ops.tapRate 1)
488+ , benchIOSink value "pollCounts 1 second" (Ops.pollCounts 1)
489+ , benchIOSink value "tapAsync" (Ops.tapAsync 1)
490+ , benchIOSink value "tapAsyncS" (Ops.tapAsyncS 1)
491+ ]
492+ ]
493+ ]
494+
495+o_1_space_serial_transformationX4 :: Int -> [Benchmark]
496+o_1_space_serial_transformationX4 value =
497+ [ bgroup
498+ "serially"
499+ [ bgroup
500+ "transformationX4"
501+ [ benchIOSink value "scan" (Ops.scan 4)
502+ , benchIOSink value "scanl1'" (Ops.scanl1' 4)
503+ , benchIOSink value "map" (Ops.map 4)
504+ , benchIOSink value "fmap" (Ops.fmap 4)
505+ , benchIOSink value "mapM" (Ops.mapM serially 4)
506+ , benchIOSink value "mapMaybe" (Ops.mapMaybe 4)
507+ , benchIOSink value "mapMaybeM" (Ops.mapMaybeM 4)
508+ -- , bench "sequence" $ nfIO $ randomRIO (1,1000) >>= \n ->
509+ -- Ops.sequence serially (Ops.sourceUnfoldrMAction n)
510+ , benchIOSink value "findIndices" (Ops.findIndices value 4)
511+ , benchIOSink value "elemIndices" (Ops.elemIndices value 4)
512+ ]
513+ ]
514+ ]
515+
516+o_1_space_serial_filtering :: Int -> [Benchmark]
517+o_1_space_serial_filtering value =
518+ [ bgroup
519+ "serially"
520+ [ bgroup
521+ "filtering"
522+ [ benchIOSink value "filter-even" (Ops.filterEven 1)
523+ , benchIOSink value "filter-all-out" (Ops.filterAllOut value 1)
524+ , benchIOSink value "filter-all-in" (Ops.filterAllIn value 1)
525+ , benchIOSink value "take-all" (Ops.takeAll value 1)
526+ , benchIOSink
527+ value
528+ "takeByTime-all"
529+ (Ops.takeByTime (NanoSecond64 maxBound) 1)
530+ , benchIOSink value "takeWhile-true" (Ops.takeWhileTrue value 1)
531+ --, benchIOSink value "takeWhileM-true" (Ops.takeWhileMTrue 1)
532+ -- "drop-one" is dual to "last"
533+ , benchIOSink value "drop-one" (Ops.dropOne 1)
534+ , benchIOSink value "drop-all" (Ops.dropAll value 1)
535+ , benchIOSink
536+ value
537+ "dropByTime-all"
538+ (Ops.dropByTime (NanoSecond64 maxBound) 1)
539+ , benchIOSink value "dropWhile-true" (Ops.dropWhileTrue value 1)
540+ --, benchIOSink value "dropWhileM-true" (Ops.dropWhileMTrue 1)
541+ , benchIOSink
542+ value
543+ "dropWhile-false"
544+ (Ops.dropWhileFalse value 1)
545+ , benchIOSink value "deleteBy" (Ops.deleteBy value 1)
546+ , benchIOSink value "intersperse" (Ops.intersperse value 1)
547+ , benchIOSink value "insertBy" (Ops.insertBy value 1)
548+ ]
549+ ]
550+ ]
551+
552+o_1_space_serial_filteringX4 :: Int -> [Benchmark]
553+o_1_space_serial_filteringX4 value =
554+ [ bgroup
555+ "serially"
556+ [ bgroup
557+ "filteringX4"
558+ [ benchIOSink value "filter-even" (Ops.filterEven 4)
559+ , benchIOSink value "filter-all-out" (Ops.filterAllOut value 4)
560+ , benchIOSink value "filter-all-in" (Ops.filterAllIn value 4)
561+ , benchIOSink value "take-all" (Ops.takeAll value 4)
562+ , benchIOSink value "takeWhile-true" (Ops.takeWhileTrue value 4)
563+ --, benchIOSink value "takeWhileM-true" (Ops.takeWhileMTrue 4)
564+ , benchIOSink value "drop-one" (Ops.dropOne 4)
565+ , benchIOSink value "drop-all" (Ops.dropAll value 4)
566+ , benchIOSink value "dropWhile-true" (Ops.dropWhileTrue value 4)
567+ --, benchIOSink value "dropWhileM-true" (Ops.dropWhileMTrue 4)
568+ , benchIOSink
569+ value
570+ "dropWhile-false"
571+ (Ops.dropWhileFalse value 4)
572+ , benchIOSink value "deleteBy" (Ops.deleteBy value 4)
573+ , benchIOSink value "intersperse" (Ops.intersperse value 4)
574+ , benchIOSink value "insertBy" (Ops.insertBy value 4)
575+ ]
576+ ]
577+ ]
578+
579+
580+o_1_space_serial_joining :: Int -> [Benchmark]
581+o_1_space_serial_joining value =
582+ [ bgroup
583+ "serially"
584+ [ bgroup
585+ "joining"
586+ [ benchIOSrc1 "zip (2,x/2)" (Ops.zip (value `div` 2))
587+ , benchIOSrc1 "zipM (2,x/2)" (Ops.zipM (value `div` 2))
588+ , benchIOSrc1 "mergeBy (2,x/2)" (Ops.mergeBy (value `div` 2))
589+ , benchIOSrc1 "serial (2,x/2)" (Ops.serial2 (value `div` 2))
590+ , benchIOSrc1 "append (2,x/2)" (Ops.append2 (value `div` 2))
591+ , benchIOSrc1 "serial (2,2,x/4)" (Ops.serial4 (value `div` 4))
592+ , benchIOSrc1 "append (2,2,x/4)" (Ops.append4 (value `div` 4))
593+ , benchIOSrc1 "wSerial (2,x/2)" (Ops.wSerial2 value) -- XXX Move this elsewhere?
594+ , benchIOSrc1 "interleave (2,x/2)" (Ops.interleave2 value)
595+ , benchIOSrc1 "roundRobin (2,x/2)" (Ops.roundRobin2 value)
596+ ]
597+ ]
598+ ]
599+
600+
601+o_1_space_serial_concatFoldable :: Int -> [Benchmark]
602+o_1_space_serial_concatFoldable value =
603+ [ bgroup
604+ "serially"
605+ [ bgroup
606+ "concat-foldable"
607+ [ benchIOSrc
608+ serially
609+ "foldMapWith"
610+ (Ops.sourceFoldMapWith value)
611+ , benchIOSrc
612+ serially
613+ "foldMapWithM"
614+ (Ops.sourceFoldMapWithM value)
615+ , benchIOSrc serially "foldMapM" (Ops.sourceFoldMapM value)
616+ , benchIOSrc
617+ serially
618+ "foldWithConcatMapId"
619+ (Ops.sourceConcatMapId value)
620+ ]
621+ ]
622+ ]
623+
624+o_1_space_serial_concatSerial :: Int -> [Benchmark]
625+o_1_space_serial_concatSerial value =
626+ [ bgroup
627+ "serially"
628+ [ bgroup
629+ "concat-serial"
630+ [ benchIOSrc1
631+ "concatMapPure (2,x/2)"
632+ (Ops.concatMapPure 2 (value `div` 2))
633+ , benchIOSrc1
634+ "concatMap (2,x/2)"
635+ (Ops.concatMap 2 (value `div` 2))
636+ , benchIOSrc1
637+ "concatMap (x/2,2)"
638+ (Ops.concatMap (value `div` 2) 2)
639+ , benchIOSrc1
640+ "concatMapRepl (x/4,4)"
641+ (Ops.concatMapRepl4xN value)
642+ , benchIOSrc1
643+ "concatUnfoldRepl (x/4,4)"
644+ (Ops.concatUnfoldRepl4xN value)
645+ , benchIOSrc1
646+ "concatMapWithSerial (2,x/2)"
647+ (Ops.concatMapWithSerial 2 (value `div` 2))
648+ , benchIOSrc1
649+ "concatMapWithSerial (x/2,2)"
650+ (Ops.concatMapWithSerial (value `div` 2) 2)
651+ , benchIOSrc1
652+ "concatMapWithAppend (2,x/2)"
653+ (Ops.concatMapWithAppend 2 (value `div` 2))
654+ ]
655+ ]
656+ ]
657+
658+
659+o_1_space_serial_outerProductStreams :: Int -> [Benchmark]
660+o_1_space_serial_outerProductStreams value =
661+ [ bgroup
662+ "serially"
663+ [ bgroup
664+ "outer-product-streams"
665+ [ benchIO "toNullAp" $ Nested.toNullAp value serially
666+ , benchIO "toNull" $ Nested.toNull value serially
667+ , benchIO "toNull3" $ Nested.toNull3 value serially
668+ , benchIO "filterAllOut" $ Nested.filterAllOut value serially
669+ , benchIO "filterAllIn" $ Nested.filterAllIn value serially
670+ , benchIO "filterSome" $ Nested.filterSome value serially
671+ , benchIO "breakAfterSome" $
672+ Nested.breakAfterSome value serially
673+ ]
674+ ]
675+ ]
676+
677+
678+o_1_space_serial_outerProductUnfolds :: Int -> [Benchmark]
679+o_1_space_serial_outerProductUnfolds value =
680+ [ bgroup
681+ "serially"
682+ [ bgroup
683+ "outer-product-unfolds"
684+ [ benchIO "toNull" $ NestedUnfold.toNull value
685+ , benchIO "toNull3" $ NestedUnfold.toNull3 value
686+ , benchIO "concat" $ NestedUnfold.concat value
687+ , benchIO "filterAllOut" $ NestedUnfold.filterAllOut value
688+ , benchIO "filterAllIn" $ NestedUnfold.filterAllIn value
689+ , benchIO "filterSome" $ NestedUnfold.filterSome value
690+ , benchIO "breakAfterSome" $ NestedUnfold.breakAfterSome value
691+ ]
692+ ]
693+ ]
694+
695+
696+o_1_space_serial_mixed :: Int -> [Benchmark]
697+o_1_space_serial_mixed value =
698+ [ bgroup
699+ "serially"
700+ -- scanl-map and foldl-map are equivalent to the scan and fold in the foldl
701+ -- library. If scan/fold followed by a map is efficient enough we may not
702+ -- need monolithic implementations of these.
703+ [ bgroup
704+ "mixed"
705+ [ benchIOSink value "scanl-map" (Ops.scanMap 1)
706+ , benchIOSink value "foldl-map" Ops.foldl'ReduceMap
707+ , benchIOSink value "sum-product-fold" Ops.sumProductFold
708+ , benchIOSink value "sum-product-scan" Ops.sumProductScan
709+ ]
710+ ]
711+ ]
712+
713+o_1_space_serial_mixedX4 :: Int -> [Benchmark]
714+o_1_space_serial_mixedX4 value =
715+ [ bgroup
716+ "serially"
717+ [ bgroup
718+ "mixedX4"
719+ [ benchIOSink value "scan-map" (Ops.scanMap 4)
720+ , benchIOSink value "drop-map" (Ops.dropMap 4)
721+ , benchIOSink value "drop-scan" (Ops.dropScan 4)
722+ , benchIOSink value "take-drop" (Ops.takeDrop value 4)
723+ , benchIOSink value "take-scan" (Ops.takeScan value 4)
724+ , benchIOSink value "take-map" (Ops.takeMap value 4)
725+ , benchIOSink value "filter-drop" (Ops.filterDrop value 4)
726+ , benchIOSink value "filter-take" (Ops.filterTake value 4)
727+ , benchIOSink value "filter-scan" (Ops.filterScan 4)
728+ , benchIOSink value "filter-scanl1" (Ops.filterScanl1 4)
729+ , benchIOSink value "filter-map" (Ops.filterMap value 4)
730+ ]
731+ ]
732+ ]
733+
734+o_1_space_wSerial_transformation :: Int -> [Benchmark]
735+o_1_space_wSerial_transformation value =
736+ [ bgroup
737+ "wSerially"
738+ [ bgroup
739+ "transformation"
740+ [benchIOSink value "fmap" $ Ops.fmap' wSerially 1]
741+ ]
742+ ]
743+
744+o_1_space_wSerial_concatMap :: Int -> [Benchmark]
745+o_1_space_wSerial_concatMap value =
746+ [ bgroup
747+ "wSerially"
748+ [ bgroup
749+ "concatMap"
750+ [ benchIOSrc1
751+ "concatMapWithWSerial (2,x/2)"
752+ (Ops.concatMapWithWSerial 2 (value `div` 2))
753+ , benchIOSrc1
754+ "concatMapWithWSerial (x/2,2)"
755+ (Ops.concatMapWithWSerial (value `div` 2) 2)
756+ ]
757+ ]
758+ ]
759+
760+o_1_space_wSerial_outerProduct :: Int -> [Benchmark]
761+o_1_space_wSerial_outerProduct value =
762+ [ bgroup
763+ "wSerially"
764+ [ bgroup
765+ "outer-product"
766+ [ benchIO "toNullAp" $ Nested.toNullAp value wSerially
767+ , benchIO "toNull" $ Nested.toNull value wSerially
768+ , benchIO "toNull3" $ Nested.toNull3 value wSerially
769+ , benchIO "filterAllOut" $ Nested.filterAllOut value wSerially
770+ , benchIO "filterAllIn" $ Nested.filterAllIn value wSerially
771+ , benchIO "filterSome" $ Nested.filterSome value wSerially
772+ , benchIO "breakAfterSome" $
773+ Nested.breakAfterSome value wSerially
774+ ]
775+ ]
776+ ]
777+
778+o_1_space_zipSerial_transformation :: Int -> [Benchmark]
779+o_1_space_zipSerial_transformation value =
780+ [ bgroup
781+ "zipSerially"
782+ [ bgroup
783+ "transformation"
784+ [benchIOSink value "fmap" $ Ops.fmap' zipSerially 1]
785+ -- XXX needs fixing
786+ {-
787+ , bgroup "outer-product"
788+ [ benchIO "toNullAp" $ Nested.toNullAp value zipSerially
789+ ]
790+ -}
791+ ]
792+ ]
benchmark/streamly-benchmarks.cabal+5−1
@@ -134,9 +134,13 @@ library
134134
135135library lib-prelude
136136 import: lib-options, bench-depends
137− hs-source-dirs: lib
137+ hs-source-dirs: lib, .
138138 exposed-modules:
139139 Streamly.Benchmark.Prelude
140+ , Streamly.Benchmark.Groups
141+ other-modules: Streamly.Benchmark.Common
142+ , NestedOps
143+ , NestedUnfoldOps
140144 -- XXX GHCJS build fails for this library.
141145 if impl(ghcjs)
142146 buildable: False