1{-# LANGUAGE ConstraintKinds #-}
3{-# LANGUAGE FlexibleContexts #-}
4{-# LANGUAGE ScopedTypeVariables #-}
7-- Module : Stream.Common
8-- Copyright : (c) 2018 Composewell Technologies
9-- License : BSD-3-Clause
10-- Maintainer : streamly@composewell.com
27 -- Benchmark stream generation
34 -- Benchmark stream elimination
39 -- Benchmarking functions
59 , transformComposeMapM
65import Control.Applicative (liftA2)
66import Control.DeepSeq (NFData)
67import Control.Exception (try)
68import GHC.Exception (ErrorCall)
69import Streamly.Internal.Data.Stream (Stream)
70import System.Random (randomRIO)
72import qualified Streamly.Internal.Data.Fold as Fold
73import qualified Streamly.Internal.Data.Pipe as Pipe
76import Streamly.Prelude (foldl', scanl')
77import qualified Streamly.Internal.Data.Stream.IsStream as Stream
78import qualified Streamly.Prelude as Stream
79import Streamly.Benchmark.Prelude
80 ( composeN, sourceConcatMapId, benchIOSink
81 , concatStreamsWith, concatPairsWith
84import qualified Streamly.Internal.Data.Stream as Stream
88import Prelude hiding (mapM, replicate)
91type MonadAsync m = Stream.MonadAsync m
93type MonadAsync = Monad
97append :: Stream m a -> Stream m a -> Stream m a
101append = Stream.append
104{-# INLINE append2 #-}
105append2 :: Monad m => Stream m a -> Stream m a -> Stream m a
107append2 = Stream.append
109append2 = Stream.append2
113drain :: Monad m => Stream m a -> m ()
114drain = Stream.fold Fold.drain
116{-# INLINE fromListM #-}
117fromListM :: MonadAsync m => [m a] -> Stream m a
119fromListM = Stream.fromListM
121fromListM = Stream.sequence . Stream.fromList
124{-# INLINE fromFoldableM #-}
125fromFoldableM :: MonadAsync m => [m a] -> Stream m a
127fromFoldableM = Stream.fromFoldableM
129fromFoldableM = Stream.sequence . Stream.fromFoldable
132{-# INLINE sourceUnfoldrM #-}
133sourceUnfoldrM :: MonadAsync m => Int -> Int -> Stream m Int
134sourceUnfoldrM count start = Stream.unfoldrM step start
139 if cnt > start + count
141 else return (Just (cnt, cnt + 1))
143{-# INLINE sourceUnfoldr #-}
144sourceUnfoldr :: Monad m => Int -> Int -> Stream m Int
145sourceUnfoldr count start = Stream.unfoldr step start
150 if cnt > start + count
152 else Just (cnt, cnt + 1)
154{-# INLINE sourceUnfoldrAction #-}
155sourceUnfoldrAction :: (Monad m1, Monad m) => Int -> Int -> Stream m (m1 Int)
156sourceUnfoldrAction value n = Stream.unfoldr step n
163 else Just (return cnt, cnt + 1)
165{-# INLINE sourceFromFoldable #-}
166sourceFromFoldable :: Int -> Int -> Stream m Int
167sourceFromFoldable value n = Stream.fromFoldable [n..n+value]
170{-# INLINE benchIOSink #-}
173 => Int -> String -> (Stream IO Int -> IO b) -> Benchmark
174benchIOSink value name f =
175 bench name $ nfIO $ randomRIO (1,1) >>= f . sourceUnfoldrM value
178-- | Takes a source, and uses it with a default drain/fold method.
179{-# INLINE benchIOSrc #-}
182 -> (Int -> Stream IO a)
185 bench name $ nfIO $ randomRIO (1,1) >>= drain . f
187{-# NOINLINE benchIO #-}
188benchIO :: (NFData b) => String -> (Int -> IO b) -> Benchmark
189benchIO name f = bench name $ nfIO $ randomRIO (1,1) >>= f
192{-# INLINE concatStreamsWith #-}
194 :: (Stream IO Int -> Stream IO Int -> Stream IO Int)
199concatStreamsWith op outer inner n =
200 drain $ Stream.concatMapWith op
201 (sourceUnfoldrM inner)
202 (sourceUnfoldrM outer n)
204{-# INLINE concatPairsWith #-}
206 :: (Stream IO Int -> Stream IO Int -> Stream IO Int)
211concatPairsWith op outer inner n =
212 drain $ Stream.concatPairsWith op
213 (sourceUnfoldrM inner)
214 (sourceUnfoldrM outer n)
216{-# INLINE sourceConcatMapId #-}
217sourceConcatMapId :: (Monad m)
218 => Int -> Int -> Stream m (Stream m Int)
219sourceConcatMapId value n =
220 Stream.fromFoldable $ fmap (Stream.fromEffect . return) [n..n+value]
223{-# INLINE apDiscardFst #-}
224apDiscardFst :: MonadAsync m =>
226apDiscardFst linearCount start = drain $
227 sourceUnfoldrM nestedCount2 start
228 *> sourceUnfoldrM nestedCount2 start
232 nestedCount2 = round (fromIntegral linearCount**(1/2::Double))
234{-# INLINE apDiscardSnd #-}
235apDiscardSnd :: MonadAsync m => Int -> Int -> m ()
236apDiscardSnd linearCount start = drain $
237 sourceUnfoldrM nestedCount2 start
238 <* sourceUnfoldrM nestedCount2 start
242 nestedCount2 = round (fromIntegral linearCount**(1/2::Double))
244{-# INLINE apLiftA2 #-}
245apLiftA2 :: MonadAsync m => Int -> Int -> m ()
246apLiftA2 linearCount start = drain $
247 liftA2 (+) (sourceUnfoldrM nestedCount2 start)
248 (sourceUnfoldrM nestedCount2 start)
252 nestedCount2 = round (fromIntegral linearCount**(1/2::Double))
254{-# INLINE toNullAp #-}
255toNullAp :: MonadAsync m => Int -> Int -> m ()
256toNullAp linearCount start = drain $
257 (+) <$> sourceUnfoldrM nestedCount2 start
258 <*> sourceUnfoldrM nestedCount2 start
262 nestedCount2 = round (fromIntegral linearCount**(1/2::Double))
264{-# INLINE monadThen #-}
265monadThen :: MonadAsync m => Int -> Int -> m ()
266monadThen linearCount start = drain $ do
267 sourceUnfoldrM nestedCount2 start >>
268 sourceUnfoldrM nestedCount2 start
272 nestedCount2 = round (fromIntegral linearCount**(1/2::Double))
274{-# INLINE toNullM #-}
275toNullM :: MonadAsync m => Int -> Int -> m ()
276toNullM linearCount start = drain $ do
277 x <- sourceUnfoldrM nestedCount2 start
278 y <- sourceUnfoldrM nestedCount2 start
283 nestedCount2 = round (fromIntegral linearCount**(1/2::Double))
285{-# INLINE toNullM3 #-}
286toNullM3 :: MonadAsync m => Int -> Int -> m ()
287toNullM3 linearCount start = drain $ do
288 x <- sourceUnfoldrM nestedCount3 start
289 y <- sourceUnfoldrM nestedCount3 start
290 z <- sourceUnfoldrM nestedCount3 start
293 nestedCount3 = round (fromIntegral linearCount**(1/3::Double))
295{-# INLINE filterAllOutM #-}
296filterAllOutM :: MonadAsync m => Int -> Int -> m ()
297filterAllOutM linearCount start = drain $ do
298 x <- sourceUnfoldrM nestedCount2 start
299 y <- sourceUnfoldrM nestedCount2 start
305 nestedCount2 = round (fromIntegral linearCount**(1/2::Double))
307{-# INLINE filterAllInM #-}
308filterAllInM :: MonadAsync m => Int -> Int -> m ()
309filterAllInM linearCount start = drain $ do
310 x <- sourceUnfoldrM nestedCount2 start
311 y <- sourceUnfoldrM nestedCount2 start
317 nestedCount2 = round (fromIntegral linearCount**(1/2::Double))
319{-# INLINE filterSome #-}
320filterSome :: MonadAsync m => Int -> Int -> m ()
321filterSome linearCount start = drain $ do
322 x <- sourceUnfoldrM nestedCount2 start
323 y <- sourceUnfoldrM nestedCount2 start
329 nestedCount2 = round (fromIntegral linearCount**(1/2::Double))
331{-# INLINE breakAfterSome #-}
332breakAfterSome :: Int -> Int -> IO ()
333breakAfterSome linearCount start = do
334 (_ :: Either ErrorCall ()) <- try $ drain $ do
335 x <- sourceUnfoldrM nestedCount2 start
336 y <- sourceUnfoldrM nestedCount2 start
343 nestedCount2 = round (fromIntegral linearCount**(1/2::Double))
345{-# INLINE toListM #-}
346toListM :: MonadAsync m => Int -> Int -> m [Int]
347toListM linearCount start = Stream.fold Fold.toList $ do
348 x <- sourceUnfoldrM nestedCount2 start
349 y <- sourceUnfoldrM nestedCount2 start
352 nestedCount2 = round (fromIntegral linearCount**(1/2::Double))
354-- Taking a specified number of elements is very expensive in logict so we have
355-- a test to measure the same.
356{-# INLINE toListSome #-}
357toListSome :: MonadAsync m => Int -> Int -> m [Int]
358toListSome linearCount start =
359 Stream.fold Fold.toList $ Stream.take 10000 $ do
360 x <- sourceUnfoldrM nestedCount2 start
361 y <- sourceUnfoldrM nestedCount2 start
364 nestedCount2 = round (fromIntegral linearCount**(1/2::Double))
367{-# INLINE composeN #-}
371 -> (Stream m Int -> Stream m Int)
378 3 -> drain . f . f . f
379 4 -> drain . f . f . f . f
389mapN n = composeN n $ fmap (+ 1)
397mapM n = composeN n $ Stream.mapM return
400foldl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> m b
401foldl' f z = Stream.fold (Fold.foldl' f z)
403scanl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
404scanl' f z = Stream.scan (Fold.foldl' f z)
407{-# INLINE transformMapM #-}
413transformMapM n = composeN n $ Stream.transform (Pipe.mapM return)
415{-# INLINE transformComposeMapM #-}
416transformComposeMapM ::
421transformComposeMapM n =
424 (Pipe.mapM (\x -> return (x + 1)) `Pipe.compose`
425 Pipe.mapM (\x -> return (x + 2)))
427{-# INLINE transformTeeMapM #-}
436 (Pipe.mapM (\x -> return (x + 1)) `Pipe.tee`
437 Pipe.mapM (\x -> return (x + 2)))
439{-# INLINE transformZipMapM #-}
450 (Pipe.mapM (\x -> return (x + 1)))
451 (Pipe.mapM (\x -> return (x + 2))))
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list