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
13{-# OPTIONS_GHC -Wno-deprecations #-}
31 -- Benchmark stream generation
38 -- Benchmark stream elimination
43 -- Benchmarking functions
63 , transformComposeMapM
69import Control.Applicative (liftA2)
70import Control.DeepSeq (NFData)
71import Control.Exception (try)
72import GHC.Exception (ErrorCall)
73import Streamly.Internal.Data.Stream (Stream)
74import System.Random (randomRIO)
76import qualified Streamly.Internal.Data.Fold as Fold
77import qualified Streamly.Internal.Data.Pipe as Pipe
80import Streamly.Prelude (foldl', scanl')
81import qualified Streamly.Internal.Data.Stream.IsStream as Stream
82import qualified Streamly.Prelude as Stream
83import Streamly.Benchmark.Prelude
84 ( composeN, sourceConcatMapId, benchIOSink
85 , concatStreamsWith, concatPairsWith
88import qualified Streamly.Internal.Data.Stream as Stream
92import Prelude hiding (mapM, replicate)
95type MonadAsync m = Stream.MonadAsync m
97type MonadAsync = Monad
101append :: Stream m a -> Stream m a -> Stream m a
103append = Stream.serial
105append = Stream.append
108{-# INLINE append2 #-}
109append2 :: Monad m => Stream m a -> Stream m a -> Stream m a
111append2 = Stream.append
113append2 = Stream.append2
117drain :: Monad m => Stream m a -> m ()
118drain = Stream.fold Fold.drain
120{-# INLINE fromListM #-}
121fromListM :: MonadAsync m => [m a] -> Stream m a
123fromListM = Stream.fromListM
125fromListM = Stream.sequence . Stream.fromList
128{-# INLINE fromFoldableM #-}
129fromFoldableM :: MonadAsync m => [m a] -> Stream m a
131fromFoldableM = Stream.fromFoldableM
133fromFoldableM = Stream.sequence . Stream.fromFoldable
136{-# INLINE sourceUnfoldrM #-}
137sourceUnfoldrM :: MonadAsync m => Int -> Int -> Stream m Int
138sourceUnfoldrM count start = Stream.unfoldrM step start
143 if cnt > start + count
145 else return (Just (cnt, cnt + 1))
147{-# INLINE sourceUnfoldr #-}
148sourceUnfoldr :: Monad m => Int -> Int -> Stream m Int
149sourceUnfoldr count start = Stream.unfoldr step start
154 if cnt > start + count
156 else Just (cnt, cnt + 1)
158{-# INLINE sourceUnfoldrAction #-}
159sourceUnfoldrAction :: (Monad m1, Monad m) => Int -> Int -> Stream m (m1 Int)
160sourceUnfoldrAction value n = Stream.unfoldr step n
167 else Just (return cnt, cnt + 1)
169{-# INLINE sourceFromFoldable #-}
170sourceFromFoldable :: Int -> Int -> Stream m Int
171sourceFromFoldable value n = Stream.fromFoldable [n..n+value]
174{-# INLINE benchIOSink #-}
177 => Int -> String -> (Stream IO Int -> IO b) -> Benchmark
178benchIOSink value name f =
179 bench name $ nfIO $ randomRIO (1,1) >>= f . sourceUnfoldrM value
182-- | Takes a source, and uses it with a default drain/fold method.
183{-# INLINE benchIOSrc #-}
186 -> (Int -> Stream IO a)
189 bench name $ nfIO $ randomRIO (1,1) >>= drain . f
191{-# NOINLINE benchIO #-}
192benchIO :: (NFData b) => String -> (Int -> IO b) -> Benchmark
193benchIO name f = bench name $ nfIO $ randomRIO (1,1) >>= f
196{-# INLINE concatStreamsWith #-}
198 :: (Stream IO Int -> Stream IO Int -> Stream IO Int)
203concatStreamsWith op outer inner n =
204 drain $ Stream.concatMapWith op
205 (sourceUnfoldrM inner)
206 (sourceUnfoldrM outer n)
208{-# INLINE concatPairsWith #-}
210 :: (Stream IO Int -> Stream IO Int -> Stream IO Int)
215concatPairsWith op outer inner n =
216 drain $ Stream.concatPairsWith op
217 (sourceUnfoldrM inner)
218 (sourceUnfoldrM outer n)
220{-# INLINE sourceConcatMapId #-}
221sourceConcatMapId :: (Monad m)
222 => Int -> Int -> Stream m (Stream m Int)
223sourceConcatMapId value n =
224 Stream.fromFoldable $ fmap (Stream.fromEffect . return) [n..n+value]
227{-# INLINE apDiscardFst #-}
228apDiscardFst :: MonadAsync m =>
230apDiscardFst linearCount start = drain $
231 sourceUnfoldrM nestedCount2 start
232 *> sourceUnfoldrM nestedCount2 start
236 nestedCount2 = round (fromIntegral linearCount**(1/2::Double))
238{-# INLINE apDiscardSnd #-}
239apDiscardSnd :: MonadAsync m => Int -> Int -> m ()
240apDiscardSnd linearCount start = drain $
241 sourceUnfoldrM nestedCount2 start
242 <* sourceUnfoldrM nestedCount2 start
246 nestedCount2 = round (fromIntegral linearCount**(1/2::Double))
248{-# INLINE apLiftA2 #-}
249apLiftA2 :: MonadAsync m => Int -> Int -> m ()
250apLiftA2 linearCount start = drain $
251 liftA2 (+) (sourceUnfoldrM nestedCount2 start)
252 (sourceUnfoldrM nestedCount2 start)
256 nestedCount2 = round (fromIntegral linearCount**(1/2::Double))
258{-# INLINE toNullAp #-}
259toNullAp :: MonadAsync m => Int -> Int -> m ()
260toNullAp linearCount start = drain $
261 (+) <$> sourceUnfoldrM nestedCount2 start
262 <*> sourceUnfoldrM nestedCount2 start
266 nestedCount2 = round (fromIntegral linearCount**(1/2::Double))
268{-# INLINE monadThen #-}
269monadThen :: MonadAsync m => Int -> Int -> m ()
270monadThen linearCount start = drain $ do
271 sourceUnfoldrM nestedCount2 start >>
272 sourceUnfoldrM nestedCount2 start
276 nestedCount2 = round (fromIntegral linearCount**(1/2::Double))
278{-# INLINE toNullM #-}
279toNullM :: MonadAsync m => Int -> Int -> m ()
280toNullM linearCount start = drain $ do
281 x <- sourceUnfoldrM nestedCount2 start
282 y <- sourceUnfoldrM nestedCount2 start
287 nestedCount2 = round (fromIntegral linearCount**(1/2::Double))
289{-# INLINE toNullM3 #-}
290toNullM3 :: MonadAsync m => Int -> Int -> m ()
291toNullM3 linearCount start = drain $ do
292 x <- sourceUnfoldrM nestedCount3 start
293 y <- sourceUnfoldrM nestedCount3 start
294 z <- sourceUnfoldrM nestedCount3 start
297 nestedCount3 = round (fromIntegral linearCount**(1/3::Double))
299{-# INLINE filterAllOutM #-}
300filterAllOutM :: MonadAsync m => Int -> Int -> m ()
301filterAllOutM linearCount start = drain $ do
302 x <- sourceUnfoldrM nestedCount2 start
303 y <- sourceUnfoldrM nestedCount2 start
309 nestedCount2 = round (fromIntegral linearCount**(1/2::Double))
311{-# INLINE filterAllInM #-}
312filterAllInM :: MonadAsync m => Int -> Int -> m ()
313filterAllInM linearCount start = drain $ do
314 x <- sourceUnfoldrM nestedCount2 start
315 y <- sourceUnfoldrM nestedCount2 start
321 nestedCount2 = round (fromIntegral linearCount**(1/2::Double))
323{-# INLINE filterSome #-}
324filterSome :: MonadAsync m => Int -> Int -> m ()
325filterSome linearCount start = drain $ do
326 x <- sourceUnfoldrM nestedCount2 start
327 y <- sourceUnfoldrM nestedCount2 start
333 nestedCount2 = round (fromIntegral linearCount**(1/2::Double))
335{-# INLINE breakAfterSome #-}
336breakAfterSome :: Int -> Int -> IO ()
337breakAfterSome linearCount start = do
338 (_ :: Either ErrorCall ()) <- try $ drain $ do
339 x <- sourceUnfoldrM nestedCount2 start
340 y <- sourceUnfoldrM nestedCount2 start
347 nestedCount2 = round (fromIntegral linearCount**(1/2::Double))
349{-# INLINE toListM #-}
350toListM :: MonadAsync m => Int -> Int -> m [Int]
351toListM linearCount start = Stream.fold Fold.toList $ do
352 x <- sourceUnfoldrM nestedCount2 start
353 y <- sourceUnfoldrM nestedCount2 start
356 nestedCount2 = round (fromIntegral linearCount**(1/2::Double))
358-- Taking a specified number of elements is very expensive in logict so we have
359-- a test to measure the same.
360{-# INLINE toListSome #-}
361toListSome :: MonadAsync m => Int -> Int -> m [Int]
362toListSome linearCount start =
363 Stream.fold Fold.toList $ Stream.take 10000 $ do
364 x <- sourceUnfoldrM nestedCount2 start
365 y <- sourceUnfoldrM nestedCount2 start
368 nestedCount2 = round (fromIntegral linearCount**(1/2::Double))
371{-# INLINE composeN #-}
375 -> (Stream m Int -> Stream m Int)
382 3 -> drain . f . f . f
383 4 -> drain . f . f . f . f
393mapN n = composeN n $ fmap (+ 1)
401mapM n = composeN n $ Stream.mapM return
404foldl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> m b
405foldl' f z = Stream.fold (Fold.foldl' f z)
407scanl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
408scanl' f z = Stream.scan (Fold.foldl' f z)
411{-# INLINE transformMapM #-}
417transformMapM n = composeN n $ Stream.transform (Pipe.mapM return)
419{-# INLINE transformComposeMapM #-}
420transformComposeMapM ::
425transformComposeMapM n =
428 (Pipe.mapM (\x -> return (x + 1)) `Pipe.compose`
429 Pipe.mapM (\x -> return (x + 2)))
431{-# INLINE transformTeeMapM #-}
440 (Pipe.mapM (\x -> return (x + 1)) `Pipe.tee`
441 Pipe.mapM (\x -> return (x + 2)))
443{-# INLINE transformZipMapM #-}
454 (Pipe.mapM (\x -> return (x + 1)))
455 (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