on efecb26 help sign in
656 lines 23 kB history raw
1-- |
2-- Module : Streamly.Benchmark.Data.Stream.StreamD
3-- Copyright : (c) 2018 Composewell Technologies
4--
5-- License : BSD3
6-- Maintainer : streamly@composewell.com
8{-# LANGUAGE CPP #-}
9{-# LANGUAGE FlexibleContexts #-}
10{-# LANGUAGE ScopedTypeVariables #-}
11{-# LANGUAGE TupleSections #-}
12{-# OPTIONS_GHC -Wno-orphans #-}
14#ifdef __HADDOCK_VERSION__
15#undef INSPECTION
16#endif
18#ifdef INSPECTION
19{-# LANGUAGE TemplateHaskell #-}
20{-# OPTIONS_GHC -fplugin Test.Inspection.Plugin #-}
21#endif
23module Main (main) where
25import Control.Applicative (liftA2)
26import Control.Monad (when)
27import Data.Maybe (isJust)
28import Gauge (bench, nfIO, bgroup, Benchmark, defaultMain)
29import System.Random (randomRIO)
30import Prelude hiding (tail, mapM_, foldl, last, map, mapM, concatMap, zip)
32import qualified Prelude as P
33import qualified Streamly.Internal.Data.Stream as S
34import qualified Streamly.Internal.Data.Unfold as UF
35import qualified Streamly.Internal.Data.Fold as FL
37import Streamly.Benchmark.Common
39#ifdef INSPECTION
40import GHC.Types (SPEC(..))
41import Test.Inspection
42#endif
44-- We try to keep the total number of iterations same irrespective of nesting
45-- of the loops so that the overhead is easy to compare.
46value, value2, value3, value16, maxValue :: Int
47value = 100000
48value2 = round (P.fromIntegral value**(1/2::P.Double)) -- double nested loop
49value3 = round (P.fromIntegral value**(1/3::P.Double)) -- triple nested loop
50value16 = round (P.fromIntegral value**(1/16::P.Double)) -- triple nested loop
51maxValue = value
53-------------------------------------------------------------------------------
54-- Stream generation and elimination
55-------------------------------------------------------------------------------
57type Stream m a = S.Stream m a
59{-# INLINE sourceUnfoldr #-}
60sourceUnfoldr :: Monad m => Int -> Stream m Int
61sourceUnfoldr n = S.unfoldr step n
62 where
63 step cnt =
64 if cnt > n + value
65 then Nothing
66 else Just (cnt, cnt + 1)
68{-# INLINE sourceUnfoldrN #-}
69sourceUnfoldrN :: Monad m => Int -> Int -> Stream m Int
70sourceUnfoldrN m n = S.unfoldr step n
71 where
72 step cnt =
73 if cnt > n + m
74 then Nothing
75 else Just (cnt, cnt + 1)
77{-# INLINE sourceUnfoldrMN #-}
78sourceUnfoldrMN :: Monad m => Int -> Int -> Stream m Int
79sourceUnfoldrMN m n = S.unfoldrM step n
80 where
81 step cnt =
82 if cnt > n + m
83 then return Nothing
84 else return (Just (cnt, cnt + 1))
86{-# INLINE sourceUnfoldrM #-}
87sourceUnfoldrM :: Monad m => Int -> Stream m Int
88sourceUnfoldrM n = S.unfoldrM step n
89 where
90 step cnt =
91 if cnt > n + value
92 then return Nothing
93 else return (Just (cnt, cnt + 1))
95{-# INLINE sourceIntFromTo #-}
96sourceIntFromTo :: Monad m => Int -> Stream m Int
97sourceIntFromTo n = S.enumerateFromToIntegral n (n + value)
99{-# INLINE sourceFromList #-}
100sourceFromList :: Monad m => Int -> Stream m Int
101sourceFromList n = S.fromList [n..n+value]
103-------------------------------------------------------------------------------
104-- Elimination
105-------------------------------------------------------------------------------
107{-# INLINE runStream #-}
108runStream :: Monad m => Stream m a -> m ()
109runStream = S.drain
111{-# INLINE mapM_ #-}
112mapM_ :: Monad m => Stream m a -> m ()
113mapM_ = S.mapM_ (\_ -> return ())
115{-# INLINE toNull #-}
116toNull :: Monad m => Stream m Int -> m ()
117toNull = runStream
119{-# INLINE uncons #-}
120{-# INLINE nullTail #-}
121{-# INLINE headTail #-}
122uncons, nullTail, headTail
123 :: Monad m
124 => Stream m Int -> m ()
126uncons s = do
127 r <- S.uncons s
128 case r of
129 Nothing -> return ()
130 Just (_, t) -> uncons t
132{-# INLINE foldBreak #-}
133foldBreak :: Monad m => Stream m Int -> m ()
134foldBreak s = do
135 (r, s1) <- S.foldBreak (FL.take 1 FL.length) s
136 when (r /= 0) $ foldBreak s1
138{-# INLINE tail #-}
139tail :: Monad m => Stream m a -> m ()
140tail s = S.tail s >>= P.mapM_ tail
142nullTail s = do
143 r <- S.null s
144 when (not r) $ S.tail s >>= P.mapM_ nullTail
146headTail s = do
147 h <- S.head s
148 when (isJust h) $ S.tail s >>= P.mapM_ headTail
150{-# INLINE toList #-}
151toList :: Monad m => Stream m Int -> m [Int]
152toList = S.toList
154{-# INLINE foldl #-}
155foldl :: Monad m => Stream m Int -> m Int
156foldl = S.foldl' (+) 0
158{-# INLINE last #-}
159last :: Monad m => Stream m Int -> m (Maybe Int)
160last = S.last
162-------------------------------------------------------------------------------
163-- Transformation
164-------------------------------------------------------------------------------
166{-# INLINE transform #-}
167transform :: Monad m => Stream m a -> m ()
168transform = runStream
170{-# INLINE composeN #-}
171composeN
172 :: Monad m
173 => Int -> (Stream m Int -> Stream m Int) -> Stream m Int -> m ()
174composeN n f =
175 case n of
176 1 -> transform . f
177 2 -> transform . f . f
178 3 -> transform . f . f . f
179 4 -> transform . f . f . f . f
180 _ -> undefined
182{-# INLINE scan #-}
183{-# INLINE map #-}
184{-# INLINE fmapD #-}
185{-# INLINE mapM #-}
186{-# INLINE mapMaybe #-}
187{-# INLINE mapMaybeM #-}
188{-# INLINE filterEven #-}
189{-# INLINE filterAllOut #-}
190{-# INLINE filterAllIn #-}
191{-# INLINE _takeOne #-}
192{-# INLINE takeAll #-}
193{-# INLINE takeWhileTrue #-}
194{-# INLINE _takeWhileMTrue #-}
195{-# INLINE dropOne #-}
196{-# INLINE dropAll #-}
197{-# INLINE dropWhileTrue #-}
198{-# INLINE _dropWhileMTrue #-}
199{-# INLINE dropWhileFalse #-}
200{-# INLINE _foldrS #-}
201{-# INLINE _foldlS #-}
202{-# INLINE intersperse #-}
203scan, map, fmapD, mapM, mapMaybe, mapMaybeM, filterEven, filterAllOut,
204 filterAllIn, _takeOne, takeAll, takeWhileTrue, _takeWhileMTrue, dropOne,
205 dropAll, dropWhileTrue, _dropWhileMTrue, dropWhileFalse, _foldrS, _foldlS,
206 intersperse
207 :: Monad m
208 => Int -> Stream m Int -> m ()
210scan n = composeN n $ S.scanl' (+) 0
211fmapD n = composeN n $ Prelude.fmap (+1)
212map n = composeN n $ S.map (+1)
213mapM n = composeN n $ S.mapM return
214mapMaybe n = composeN n $ S.mapMaybe
215 (\x -> if Prelude.odd x then Nothing else Just x)
216mapMaybeM n = composeN n $ S.mapMaybeM
217 (\x -> if Prelude.odd x then return Nothing else return $ Just x)
218filterEven n = composeN n $ S.filter even
219filterAllOut n = composeN n $ S.filter (> maxValue)
220filterAllIn n = composeN n $ S.filter (<= maxValue)
221_takeOne n = composeN n $ S.take 1
222takeAll n = composeN n $ S.take maxValue
223takeWhileTrue n = composeN n $ S.takeWhile (<= maxValue)
224_takeWhileMTrue n = composeN n $ S.takeWhileM (return . (<= maxValue))
225dropOne n = composeN n $ S.drop 1
226dropAll n = composeN n $ S.drop maxValue
227dropWhileTrue n = composeN n $ S.dropWhile (<= maxValue)
228_dropWhileMTrue n = composeN n $ S.dropWhileM (return . (<= maxValue))
229dropWhileFalse n = composeN n $ S.dropWhile (> maxValue)
230_foldrS n = composeN n $ S.foldrS S.cons S.nil
231_foldlS n = composeN n $ S.foldlS (flip S.cons) S.nil
232intersperse n = composeN n $ S.intersperse maxValue
234-------------------------------------------------------------------------------
235-- Iteration
236-------------------------------------------------------------------------------
238iterStreamLen, maxIters :: Int
239iterStreamLen = 10
240maxIters = 10000
242{-# INLINE iterateSource #-}
243iterateSource
244 :: Monad m
245 => (Stream m Int -> Stream m Int) -> Int -> Int -> Stream m Int
246iterateSource g i n = f i (sourceUnfoldrMN iterStreamLen n)
247 where
248 f (0 :: Int) m = g m
249 f x m = g (f (x P.- 1) m)
251{-# INLINE iterateMapM #-}
252{-# INLINE iterateScan #-}
253{-# INLINE iterateFilterEven #-}
254{-# INLINE iterateTakeAll #-}
255{-# INLINE iterateDropOne #-}
256{-# INLINE iterateDropWhileFalse #-}
257{-# INLINE iterateDropWhileTrue #-}
258iterateMapM, iterateScan, iterateFilterEven, iterateTakeAll, iterateDropOne,
259 iterateDropWhileFalse, iterateDropWhileTrue
260 :: Monad m
261 => Int -> Stream m Int
263-- this is quadratic
264iterateScan = iterateSource (S.scanl' (+) 0) (maxIters `div` 10)
265iterateDropWhileFalse = iterateSource (S.dropWhile (> maxValue))
266 (maxIters `div` 10)
268iterateMapM = iterateSource (S.mapM return) maxIters
269iterateFilterEven = iterateSource (S.filter even) maxIters
270iterateTakeAll = iterateSource (S.take maxValue) maxIters
271iterateDropOne = iterateSource (S.drop 1) maxIters
272iterateDropWhileTrue = iterateSource (S.dropWhile (<= maxValue)) maxIters
274{-# INLINE iterateM #-}
275iterateM :: Monad m => Int -> Stream m Int
276iterateM i = S.take maxIters (S.iterateM (\x -> return (x + 1)) (return i))
278-------------------------------------------------------------------------------
279-- Zipping
280-------------------------------------------------------------------------------
282{-# INLINE eqBy #-}
283eqBy :: (Monad m, P.Eq a) => S.Stream m a -> m P.Bool
284eqBy src = S.eqBy (==) src src
286{-# INLINE cmpBy #-}
287cmpBy :: (Monad m, P.Ord a) => S.Stream m a -> m P.Ordering
288cmpBy src = S.cmpBy P.compare src src
290{-# INLINE zip #-}
291zip :: Monad m => Stream m Int -> m ()
292zip src = transform $ S.zipWith (,) src src
294-------------------------------------------------------------------------------
295-- Mixed Composition
296-------------------------------------------------------------------------------
298{-# INLINE scanMap #-}
299{-# INLINE dropMap #-}
300{-# INLINE dropScan #-}
301{-# INLINE takeDrop #-}
302{-# INLINE takeScan #-}
303{-# INLINE takeMap #-}
304{-# INLINE filterDrop #-}
305{-# INLINE filterTake #-}
306{-# INLINE filterScan #-}
307{-# INLINE filterMap #-}
308scanMap, dropMap, dropScan, takeDrop, takeScan, takeMap, filterDrop,
309 filterTake, filterScan, filterMap
310 :: Monad m => Int -> Stream m Int -> m ()
312scanMap n = composeN n $ S.map (subtract 1) . S.scanl' (+) 0
313dropMap n = composeN n $ S.map (subtract 1) . S.drop 1
314dropScan n = composeN n $ S.scanl' (+) 0 . S.drop 1
315takeDrop n = composeN n $ S.drop 1 . S.take maxValue
316takeScan n = composeN n $ S.scanl' (+) 0 . S.take maxValue
317takeMap n = composeN n $ S.map (subtract 1) . S.take maxValue
318filterDrop n = composeN n $ S.drop 1 . S.filter (<= maxValue)
319filterTake n = composeN n $ S.take maxValue . S.filter (<= maxValue)
320filterScan n = composeN n $ S.scanl' (+) 0 . S.filter (<= maxBound)
321filterMap n = composeN n $ S.map (subtract 1) . S.filter (<= maxValue)
323-------------------------------------------------------------------------------
324-- Nested Composition
325-------------------------------------------------------------------------------
327instance Monad f => Applicative (S.Stream f) where
328 {-# INLINE pure #-}
329 pure = S.fromPure
331 {-# INLINE (<*>) #-}
332 (<*>) = S.crossApply
334 {-# INLINE liftA2 #-}
335 liftA2 f x = (<*>) (fmap f x)
337 {-# INLINE (*>) #-}
338 (*>) = S.crossApplySnd
340 {-# INLINE (<*) #-}
341 (<*) = S.crossApplyFst
343-- NOTE: even though concatMap for StreamD is 4x faster compared to StreamK,
344-- the monad instance does not seem to be significantly faster.
345instance Monad m => Monad (S.Stream m) where
346 {-# INLINE return #-}
347 return = pure
349 {-# INLINE (>>=) #-}
350 (>>=) = flip S.concatMap
352 {-# INLINE (>>) #-}
353 (>>) = (*>)
355{-# INLINE toNullApNested #-}
356toNullApNested :: Monad m => Stream m Int -> m ()
357toNullApNested s = runStream $ do
358 (+) <$> s <*> s
360{-# INLINE toNullNested #-}
361toNullNested :: Monad m => Stream m Int -> m ()
362toNullNested s = runStream $ do
363 x <- s
364 y <- s
365 return $ x + y
367{-# INLINE toNullNested3 #-}
368toNullNested3 :: Monad m => Stream m Int -> m ()
369toNullNested3 s = runStream $ do
370 x <- s
371 y <- s
372 z <- s
373 return $ x + y + z
375{-# INLINE filterAllOutNested #-}
376filterAllOutNested
377 :: Monad m
378 => Stream m Int -> m ()
379filterAllOutNested str = runStream $ do
380 x <- str
381 y <- str
382 let s = x + y
383 if s < 0
384 then return s
385 else S.nil
387{-# INLINE filterAllInNested #-}
388filterAllInNested
389 :: Monad m
390 => Stream m Int -> m ()
391filterAllInNested str = runStream $ do
392 x <- str
393 y <- str
394 let s = x + y
395 if s > 0
396 then return s
397 else S.nil
399-------------------------------------------------------------------------------
400-- ConcatMap
401-------------------------------------------------------------------------------
403-- concatMap unfoldrM/unfoldrM
405{-# INLINE concatMap #-}
406concatMap :: Int -> Int -> Int -> IO ()
407concatMap outer inner n =
408 S.drain $ S.concatMap
409 (\_ -> sourceUnfoldrMN inner n)
410 (sourceUnfoldrMN outer n)
412#ifdef INSPECTION
413inspect $ hasNoTypeClasses 'concatMap
414inspect $ 'concatMap `hasNoType` ''SPEC
415#endif
417-- concatMap unfoldr/unfoldr
419{-# INLINE concatMapPure #-}
420concatMapPure :: Int -> Int -> Int -> IO ()
421concatMapPure outer inner n =
422 S.drain $ S.concatMap
423 (\_ -> sourceUnfoldrN inner n)
424 (sourceUnfoldrN outer n)
426#ifdef INSPECTION
427inspect $ hasNoTypeClasses 'concatMapPure
428inspect $ 'concatMapPure `hasNoType` ''SPEC
429#endif
431-- concatMap replicate/unfoldrM
433{-# INLINE concatMapRepl #-}
434concatMapRepl :: Int -> Int -> Int -> IO ()
435concatMapRepl outer inner n =
436 S.drain $ S.concatMap (S.replicate inner) (sourceUnfoldrMN outer n)
438#ifdef INSPECTION
439inspect $ hasNoTypeClasses 'concatMapRepl
440inspect $ 'concatMapRepl `hasNoType` ''SPEC
441#endif
443-- unfoldMany replicate/unfoldrM
445{-# INLINE unfoldManyRepl #-}
446unfoldManyRepl :: Int -> Int -> Int -> IO ()
447unfoldManyRepl outer inner n =
448 S.drain
449 $ S.unfoldMany
450 UF.replicateM
451 (S.map ((inner,) . return) (sourceUnfoldrMN outer n))
453#ifdef INSPECTION
454inspect $ hasNoTypeClasses 'unfoldManyRepl
455inspect $ 'unfoldManyRepl `hasNoType` ''S.ConcatMapUState
456inspect $ 'unfoldManyRepl `hasNoType` ''SPEC
457#endif
459-------------------------------------------------------------------------------
460-- Benchmarks
461-------------------------------------------------------------------------------
463moduleName :: String
464moduleName = "Data.StreamD"
466o_1_space :: [Benchmark]
467o_1_space =
468 [ bgroup (o_1_space_prefix moduleName)
469 [ bgroup "generation"
470 [ benchFold "unfoldr" toNull sourceUnfoldr
471 , benchFold "unfoldrM" toNull sourceUnfoldrM
472 , benchFold "intFromTo" toNull sourceIntFromTo
474 , benchFold "fromList" toNull sourceFromList
475 ]
476 , bgroup "elimination"
477 [ benchFold "toNull" toNull sourceUnfoldrM
478 , benchFold "mapM_" mapM_ sourceUnfoldrM
479 , benchFold "uncons" uncons sourceUnfoldrM
480 , benchFold "foldBreak" foldBreak sourceUnfoldrM
481 , benchFold "foldl'" foldl sourceUnfoldrM
482 , benchFold "last" last sourceUnfoldrM
483 ]
484 , bgroup "nested"
485 [ benchFold "toNullAp" toNullApNested (sourceUnfoldrMN value2)
486 , benchFold "toNull" toNullNested (sourceUnfoldrMN value2)
487 , benchFold "toNull3" toNullNested3 (sourceUnfoldrMN value3)
488 , benchFold "filterAllIn" filterAllInNested (sourceUnfoldrMN value2)
489 , benchFold "filterAllOut" filterAllOutNested (sourceUnfoldrMN value2)
490 , benchFold "toNullApPure" toNullApNested (sourceUnfoldrN value2)
491 , benchFold "toNullPure" toNullNested (sourceUnfoldrN value2)
492 , benchFold "toNull3Pure" toNullNested3 (sourceUnfoldrN value3)
493 , benchFold "filterAllInPure" filterAllInNested (sourceUnfoldrN value2)
494 , benchFold "filterAllOutPure" filterAllOutNested (sourceUnfoldrN value2)
495 ]
496 , bgroup "transformation"
497 [ benchFold "scan" (scan 1) sourceUnfoldrM
498 , benchFold "map" (map 1) sourceUnfoldrM
499 , benchFold "fmap" (fmapD 1) sourceUnfoldrM
500 , benchFold "mapM" (mapM 1) sourceUnfoldrM
501 , benchFold "mapMaybe" (mapMaybe 1) sourceUnfoldrM
502 , benchFold "mapMaybeM" (mapMaybeM 1) sourceUnfoldrM
503 ]
504 , bgroup "transformationX4"
505 [ benchFold "scan" (scan 4) sourceUnfoldrM
506 , benchFold "map" (map 4) sourceUnfoldrM
507 , benchFold "fmap" (fmapD 4) sourceUnfoldrM
508 , benchFold "mapM" (mapM 4) sourceUnfoldrM
509 , benchFold "mapMaybe" (mapMaybe 4) sourceUnfoldrM
510 , benchFold "mapMaybeM" (mapMaybeM 4) sourceUnfoldrM
511 -- XXX this is horribly slow
512 -- , benchFold "concatMap" (concatMap 4) (sourceUnfoldrMN value16)
513 ]
515 , bgroup "concat"
516 [ benchIOSrc1 "concatMapPure (n of 1)"
517 (concatMapPure value 1)
518 , benchIOSrc1 "concatMapPure (sqrt n of sqrt n)"
519 (concatMapPure value2 value2)
520 , benchIOSrc1 "concatMapPure (1 of n)"
521 (concatMapPure 1 value)
523 , benchIOSrc1 "concatMap (n of 1)"
524 (concatMap value 1)
525 , benchIOSrc1 "concatMap (sqrt n of sqrt n)"
526 (concatMap value2 value2)
527 , benchIOSrc1 "concatMap (1 of n)"
528 (concatMap 1 value)
530 -- concatMap vs unfoldMany
531 , benchIOSrc1 "concatMapRepl (sqrt n of sqrt n)"
532 (concatMapRepl value2 value2)
533 , benchIOSrc1 "unfoldManyRepl (sqrt n of sqrt n)"
534 (unfoldManyRepl value2 value2)
535 ]
536 , bgroup "filtering"
537 [ benchFold "filter-even" (filterEven 1) sourceUnfoldrM
538 , benchFold "filter-all-out" (filterAllOut 1) sourceUnfoldrM
539 , benchFold "filter-all-in" (filterAllIn 1) sourceUnfoldrM
540 , benchFold "take-all" (takeAll 1) sourceUnfoldrM
541 , benchFold "takeWhile-true" (takeWhileTrue 1) sourceUnfoldrM
542 , benchFold "drop-one" (dropOne 1) sourceUnfoldrM
543 , benchFold "drop-all" (dropAll 1) sourceUnfoldrM
544 , benchFold "dropWhile-true" (dropWhileTrue 1) sourceUnfoldrM
545 , benchFold "dropWhile-false" (dropWhileFalse 1) sourceUnfoldrM
546 ]
547 , bgroup "filteringX4"
548 [ benchFold "filter-even" (filterEven 4) sourceUnfoldrM
549 , benchFold "filter-all-out" (filterAllOut 4) sourceUnfoldrM
550 , benchFold "filter-all-in" (filterAllIn 4) sourceUnfoldrM
551 , benchFold "take-all" (takeAll 4) sourceUnfoldrM
552 , benchFold "takeWhile-true" (takeWhileTrue 4) sourceUnfoldrM
553 , benchFold "drop-one" (dropOne 4) sourceUnfoldrM
554 , benchFold "drop-all" (dropAll 4) sourceUnfoldrM
555 , benchFold "dropWhile-true" (dropWhileTrue 4) sourceUnfoldrM
556 , benchFold "dropWhile-false" (dropWhileFalse 4) sourceUnfoldrM
557 ]
558 , bgroup "zipping"
559 [ benchFold "eqBy" eqBy sourceUnfoldrM
560 , benchFold "cmpBy" cmpBy sourceUnfoldrM
561 , benchFold "zip" zip sourceUnfoldrM
562 ]
563 , bgroup "mixed"
564 [ benchFold "scan-map" (scanMap 1) sourceUnfoldrM
565 , benchFold "drop-map" (dropMap 1) sourceUnfoldrM
566 , benchFold "drop-scan" (dropScan 1) sourceUnfoldrM
567 , benchFold "take-drop" (takeDrop 1) sourceUnfoldrM
568 , benchFold "take-scan" (takeScan 1) sourceUnfoldrM
569 , benchFold "take-map" (takeMap 1) sourceUnfoldrM
570 , benchFold "filter-drop" (filterDrop 1) sourceUnfoldrM
571 , benchFold "filter-take" (filterTake 1) sourceUnfoldrM
572 , benchFold "filter-scan" (filterScan 1) sourceUnfoldrM
573 , benchFold "filter-map" (filterMap 1) sourceUnfoldrM
574 ]
575 , bgroup "mixedX2"
576 [ benchFold "scan-map" (scanMap 2) sourceUnfoldrM
577 , benchFold "drop-map" (dropMap 2) sourceUnfoldrM
578 , benchFold "drop-scan" (dropScan 2) sourceUnfoldrM
579 , benchFold "take-drop" (takeDrop 2) sourceUnfoldrM
580 , benchFold "take-scan" (takeScan 2) sourceUnfoldrM
581 , benchFold "take-map" (takeMap 2) sourceUnfoldrM
582 , benchFold "filter-drop" (filterDrop 2) sourceUnfoldrM
583 , benchFold "filter-take" (filterTake 2) sourceUnfoldrM
584 , benchFold "filter-scan" (filterScan 2) sourceUnfoldrM
585 , benchFold "filter-map" (filterMap 2) sourceUnfoldrM
586 ]
587 , bgroup "mixedX4"
588 [ benchFold "scan-map" (scanMap 4) sourceUnfoldrM
589 , benchFold "drop-map" (dropMap 4) sourceUnfoldrM
590 , benchFold "drop-scan" (dropScan 4) sourceUnfoldrM
591 , benchFold "take-drop" (takeDrop 4) sourceUnfoldrM
592 , benchFold "take-scan" (takeScan 4) sourceUnfoldrM
593 , benchFold "take-map" (takeMap 4) sourceUnfoldrM
594 , benchFold "filter-drop" (filterDrop 4) sourceUnfoldrM
595 , benchFold "filter-take" (filterTake 4) sourceUnfoldrM
596 , benchFold "filter-scan" (filterScan 4) sourceUnfoldrM
597 , benchFold "filter-map" (filterMap 4) sourceUnfoldrM
598 ]
599 ]
600 ]
602-- | Takes a source, and uses it with a default drain/fold method.
603{-# INLINE benchD #-}
604benchD :: P.String -> (Int -> Stream P.IO Int) -> Benchmark
605benchD name f = bench name $ nfIO $ randomRIO (1,1) >>= toNull . f
607o_n_stack :: [Benchmark]
608o_n_stack =
609 [ bgroup (o_n_stack_prefix moduleName)
610 [ bgroup "elimination"
611 [ benchFold "tail" tail sourceUnfoldrM
612 , benchFold "nullTail" nullTail sourceUnfoldrM
613 , benchFold "headTail" headTail sourceUnfoldrM
614 ]
615 , bgroup "transformation"
616 [
617 -- this is horribly slow
618 -- benchFold "foldrS" (_foldrS 1) sourceUnfoldrM
619 -- XXX why do these need so much stack
620 benchFold "intersperse" (intersperse 1) (sourceUnfoldrMN value2)
621 , benchFold "interspersePure" (intersperse 1) (sourceUnfoldrN value2)
622 ]
623 , bgroup "transformationX4"
624 [
625 benchFold "intersperse" (intersperse 4) (sourceUnfoldrMN value16)
626 ]
627 , bgroup "iterated"
628 [ benchD "mapM" iterateMapM
629 , benchD "scan(1/10)" iterateScan
630 , benchD "filterEven" iterateFilterEven
631 , benchD "takeAll" iterateTakeAll
632 , benchD "dropOne" iterateDropOne
633 , benchD "dropWhileFalse(1/10)" iterateDropWhileFalse
634 , benchD "dropWhileTrue" iterateDropWhileTrue
635 , benchD "iterateM" iterateM
636 ]
637 ]
638 ]
640o_n_space :: [Benchmark]
641o_n_space =
642 [ bgroup (o_n_space_prefix moduleName)
643 [ bgroup "elimination"
644 [ benchFold "toList" toList sourceUnfoldrM
645 ]
646 , bgroup "transformation"
647 [
649 -- This is horribly slow, never finishes
650 -- benchFold "foldlS" (_foldlS 1) sourceUnfoldrM
651 ]
652 ]
653 ]
655main :: IO ()
656main = defaultMain $ concat [o_1_space, o_n_stack, o_n_space]