2-- Module : Stream.Generate
3-- Copyright : (c) 2018 Composewell Technologies
4-- License : BSD-3-Clause
5-- Maintainer : streamly@composewell.com
8{-# LANGUAGE FlexibleContexts #-}
9{-# LANGUAGE FlexibleInstances #-}
10{-# LANGUAGE ScopedTypeVariables #-}
11{-# LANGUAGE RankNTypes #-}
13{-# OPTIONS_GHC -Wno-orphans #-}
15{-# OPTIONS_GHC -Wno-deprecations #-}
18module Stream.Generate (benchmarks) where
20import Control.DeepSeq (NFData(..))
21import Data.Functor.Identity (Identity(..))
23import qualified GHC.Exts as GHC
24import qualified Streamly.Internal.Data.Fold as Fold
27import Streamly.Prelude (MonadAsync)
28import Stream.Common hiding (MonadAsync)
29import Streamly.Benchmark.Prelude (sourceFromFoldableM, absTimes)
30import qualified Streamly.Prelude as S
31import qualified Streamly.Internal.Data.Stream.IsStream as Stream
34import Streamly.Internal.Data.Stream (Stream)
35import qualified Streamly.Internal.Data.Stream as Stream
37import System.IO.Unsafe (unsafeInterleaveIO)
38import qualified Streamly.Internal.Data.StreamK as StreamK
39import qualified Stream.Common as Common
44import Streamly.Benchmark.Common
45import qualified Prelude
47import Prelude hiding (repeat, replicate, iterate)
49-------------------------------------------------------------------------------
51-------------------------------------------------------------------------------
54type Stream = Stream.SerialT
55toStreamD = Stream.toStream
61-------------------------------------------------------------------------------
63-------------------------------------------------------------------------------
65{-# INLINE sourceFromList #-}
66sourceFromList :: Monad m => Int -> Int -> Stream m Int
67sourceFromList value n = Stream.fromList [n..n+value]
69{-# INLINE sourceFromListM #-}
70sourceFromListM :: MonadAsync m => Int -> Int -> Stream m Int
71sourceFromListM value n = fromListM (fmap return [n..n+value])
73{-# INLINE sourceIsList #-}
74sourceIsList :: Int -> Int -> Stream Identity Int
75sourceIsList value n = GHC.fromList [n..n+value]
77{-# INLINE sourceIsString #-}
78sourceIsString :: Int -> Int -> Stream Identity Char
79sourceIsString value n = GHC.fromString (Prelude.replicate (n + value) 'a')
81{-# INLINE readInstance #-}
82readInstance :: String -> Stream Identity Int
87 _ -> error "readInstance: no parse"
90{-# INLINE readInstanceList #-}
91readInstanceList :: String -> [Int]
96 _ -> error "readInstance: no parse"
99repeat :: Monad m => Int -> Int -> Stream m Int
100repeat count = Stream.take count . Stream.repeat
102{-# INLINE replicate #-}
103replicate :: Monad m => Int -> Int -> Stream m Int
104replicate = Stream.replicate
106-------------------------------------------------------------------------------
108-------------------------------------------------------------------------------
110{-# INLINE sourceIntFromTo #-}
111sourceIntFromTo :: Monad m => Int -> Int -> Stream m Int
112sourceIntFromTo value n = Stream.enumerateFromTo n (n + value)
114{-# INLINE sourceIntFromThenTo #-}
115sourceIntFromThenTo :: Monad m => Int -> Int -> Stream m Int
116sourceIntFromThenTo value n = Stream.enumerateFromThenTo n (n + 1) (n + value)
118{-# INLINE sourceFracFromTo #-}
119sourceFracFromTo :: Monad m => Int -> Int -> Stream m Double
120sourceFracFromTo value n =
121 Stream.enumerateFromTo (fromIntegral n) (fromIntegral (n + value))
123{-# INLINE sourceFracFromThenTo #-}
124sourceFracFromThenTo :: Monad m => Int -> Int -> Stream m Double
125sourceFracFromThenTo value n = Stream.enumerateFromThenTo (fromIntegral n)
126 (fromIntegral n + 1.0001) (fromIntegral (n + value))
128{-# INLINE sourceIntegerFromStep #-}
129sourceIntegerFromStep :: Monad m => Int -> Int -> Stream m Integer
130sourceIntegerFromStep value n =
131 Stream.take value $ Stream.enumerateFromThen (fromIntegral n) (fromIntegral n + 1)
133{-# INLINE enumerateFrom #-}
134enumerateFrom :: Monad m => Int -> Int -> Stream m Int
135enumerateFrom count = Stream.take count . Stream.enumerateFrom
137{-# INLINE enumerateFromTo #-}
138enumerateFromTo :: Monad m => Int -> Int -> Stream m Int
139enumerateFromTo = sourceIntFromTo
141{-# INLINE enumerateFromThen #-}
142enumerateFromThen :: Monad m => Int -> Int -> Stream m Int
143enumerateFromThen count inp = Stream.take count $ Stream.enumerateFromThen inp (inp + 1)
145{-# INLINE enumerateFromThenTo #-}
146enumerateFromThenTo :: Monad m => Int -> Int -> Stream m Int
147enumerateFromThenTo = sourceIntFromThenTo
150{-# INLINE enumerate #-}
151enumerate :: Monad m => Int -> Int -> Stream m Int
152enumerate count n = Stream.take (count + n) Stream.enumerate
155{-# INLINE enumerateTo #-}
156enumerateTo :: Monad m => Int -> Int -> Stream m Int
157enumerateTo count n = Stream.enumerateTo (minBound + count + n)
159{-# INLINE iterate #-}
160iterate :: Monad m => Int -> Int -> Stream m Int
161iterate count = Stream.take count . Stream.iterate (+1)
163{-# INLINE iterateM #-}
164iterateM :: MonadAsync m => Int -> Int -> Stream m Int
165iterateM count = Stream.take count . Stream.iterateM (return . (+1)) . return
167{-# INLINE repeatM #-}
168repeatM :: MonadAsync m => Int -> Int -> Stream m Int
169repeatM count = Stream.take count . Stream.repeatM . return
171{-# INLINE replicateM #-}
172replicateM :: MonadAsync m => Int -> Int -> Stream m Int
173replicateM count = Stream.replicateM count . return
176{-# INLINE fromIndices #-}
177fromIndices :: (Monad m, S.IsStream t) => Int -> Int -> t m Int
178fromIndices value n = S.take value $ S.fromIndices (+ n)
180{-# INLINE fromIndicesM #-}
181fromIndicesM :: (MonadAsync m, S.IsStream t) => Int -> Int -> t m Int
182fromIndicesM value n = S.take value $ S.fromIndicesM (return <$> (+ n))
186{-# INLINE mfixUnfold #-}
187mfixUnfold :: Int -> Int -> Stream IO (Int, Int)
188mfixUnfold count start = toStream $ StreamK.mfix f
190 f action = StreamK.unCross $ do
191 let incr n act = fmap ((+n) . snd) $ unsafeInterleaveIO act
192 x <- StreamK.mkCross (fromStream $ Common.fromListM [incr 1 action, incr 2 action])
193 y <- StreamK.mkCross (fromStream $ Common.sourceUnfoldr count start)
197o_1_space_generation :: Int -> [Benchmark]
198o_1_space_generation value =
199 [ bgroup "generation"
200 [ benchIOSrc "unfoldr" (sourceUnfoldr value)
201 , benchIOSrc "unfoldrM" (sourceUnfoldrM value)
202 , benchIOSrc "repeat" (repeat value)
203 , benchIOSrc "replicate" (replicate value)
204 , benchIOSrc "iterate" (iterate value)
205 , benchIOSrc "iterateM" (iterateM value)
206 , benchIOSrc "intFromTo" (sourceIntFromTo value)
207 , benchIOSrc "intFromThenTo" (sourceIntFromThenTo value)
208 , benchIOSrc "integerFromStep" (sourceIntegerFromStep value)
209 , benchIOSrc "fracFromThenTo" (sourceFracFromThenTo value)
210 , benchIOSrc "fracFromTo" (sourceFracFromTo value)
211 , benchIOSrc "fromList" (sourceFromList value)
212 , benchIOSrc "fromListM" (sourceFromListM value)
213 , benchPureSrc "IsList.fromList" (toStreamD . sourceIsList value)
214 , benchPureSrc "IsString.fromString" (toStreamD . sourceIsString value)
215 , benchIOSrc "enumerateFrom" (enumerateFrom value)
216 , benchIOSrc "enumerateFromTo" (enumerateFromTo value)
217 , benchIOSrc "enumerateFromThen" (enumerateFromThen value)
218 , benchIOSrc "enumerateFromThenTo" (enumerateFromThenTo value)
219 , benchIOSrc "enumerate" (enumerate value)
220 , benchIOSrc "enumerateTo" (enumerateTo value)
221 , benchIOSrc "repeatM" (repeatM value)
222 , benchIOSrc "replicateM" (replicateM value)
224 , benchIOSrc "fromIndices" (fromIndices value)
225 , benchIOSrc "fromIndicesM" (fromIndicesM value)
228 -- These essentially test cons and consM
230 , benchIOSrc "fromFoldable" (sourceFromFoldable value)
231 -- , benchIOSrc "fromFoldable 16" (sourceFromFoldable 16)
233 -- , benchIOSrc "fromFoldable 16" (sourceFromFoldable 16)
237 , benchIOSrc "fromFoldableM" (sourceFromFoldableM value)
238 , benchIOSrc "absTimes" $ absTimes value
241 , Common.benchIOSrc "mfix_10" (mfixUnfold 10)
242 , Common.benchIOSrc "mfix_100" (mfixUnfold 100)
243 , Common.benchIOSrc "mfix_1000" (mfixUnfold 1000)
249instance NFData a => NFData (Stream Identity a) where
251 rnf xs = runIdentity $ Stream.fold (Fold.foldl' (\_ x -> rnf x) ()) xs
254o_n_heap_generation :: Int -> [Benchmark]
255o_n_heap_generation value =
257 -- Buffers the output of show/read.
258 -- XXX can the outputs be streaming? Can we have special read/show
259 -- style type classes, readM/showM supporting streaming effects?
260 [ bench "readsPrec pure streams" $
261 nf readInstance (mkString value)
262 , bench "readsPrec Haskell lists" $
263 nf readInstanceList (mkListString value)
267-------------------------------------------------------------------------------
269-------------------------------------------------------------------------------
271-- In addition to gauge options, the number of elements in the stream can be
272-- passed using the --stream-size option.
274benchmarks :: String -> Int -> [Benchmark]
275benchmarks moduleName size =
276 [ bgroup (o_1_space_prefix moduleName) (o_1_space_generation size)
277 , bgroup (o_n_heap_prefix moduleName) (o_n_heap_generation size)
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