on bf4e5d8 help sign in
streamly/benchmark/StreamKOps.hs
279 lines 8.7 kB history raw
1-- |
2-- Module : StreamKOps
3-- Copyright : (c) 2018 Harendra Kumar
4--
5-- License : BSD3
6-- Maintainer : harendra.kumar@gmail.com
8{-# LANGUAGE FlexibleContexts #-}
9{-# LANGUAGE ScopedTypeVariables #-}
11module StreamKOps where
13import Control.Monad (when)
14import Data.Maybe (isJust)
15import Prelude
16 (Monad, Int, (+), ($), (.), return, even, (>), (<=), div,
17 subtract, undefined, Maybe(..), not, mapM_, (>>=),
18 maxBound)
19import qualified Prelude as P
21import qualified Streamly.Streams.StreamK as S
22import qualified Streamly.Streams.Prelude as S
23import qualified Streamly.SVar as S
25value, maxValue :: Int
26value = 100000
27maxValue = value + 1000
29-------------------------------------------------------------------------------
30-- Benchmark ops
31-------------------------------------------------------------------------------
33{-# INLINE toNull #-}
34{-# INLINE uncons #-}
35{-# INLINE nullTail #-}
36{-# INLINE headTail #-}
37{-# INLINE zip #-}
38{-# INLINE concat #-}
39toNull, uncons, nullTail, headTail, zip, concat
40 :: Monad m
41 => Stream m Int -> m ()
43{-# INLINE toList #-}
44toList :: Monad m => Stream m Int -> m [Int]
45{-# INLINE foldl #-}
46foldl :: Monad m => Stream m Int -> m Int
47{-# INLINE last #-}
48last :: Monad m => Stream m Int -> m (Maybe Int)
50-------------------------------------------------------------------------------
51-- Stream generation and elimination
52-------------------------------------------------------------------------------
54type Stream m a = S.Stream m a
56{-# INLINE sourceUnfoldr #-}
57sourceUnfoldr :: Int -> Stream m Int
58sourceUnfoldr n = S.unfoldr step n
59 where
60 step cnt =
61 if cnt > n + value
62 then Nothing
63 else Just (cnt, cnt + 1)
65{-# INLINE sourceUnfoldrM #-}
66sourceUnfoldrM :: S.MonadAsync m => Int -> Stream m Int
67sourceUnfoldrM n = S.unfoldrM step n
68 where
69 step cnt =
70 if cnt > n + value
71 then return Nothing
72 else return (Just (cnt, cnt + 1))
74{-# INLINE sourceUnfoldrMN #-}
75sourceUnfoldrMN :: S.MonadAsync m => Int -> Int -> Stream m Int
76sourceUnfoldrMN m n = S.unfoldrM step n
77 where
78 step cnt =
79 if cnt > n + m
80 then return Nothing
81 else return (Just (cnt, cnt + 1))
83{-
84{-# INLINE sourceFromEnum #-}
85sourceFromEnum :: Monad m => Int -> Stream m Int
86sourceFromEnum n = S.enumFromStepN n 1 value
87-}
89{-# INLINE sourceFromFoldable #-}
90sourceFromFoldable :: Int -> Stream m Int
91sourceFromFoldable n = S.fromFoldable [n..n+value]
93{-
94{-# INLINE sourceFromFoldableM #-}
95sourceFromFoldableM :: S.MonadAsync m => Int -> Stream m Int
96sourceFromFoldableM n = S.fromFoldableM (Prelude.fmap return [n..n+value])
97-}
99{-# INLINE sourceFoldMapWith #-}
100sourceFoldMapWith :: Int -> Stream m Int
101sourceFoldMapWith n = S.foldMapWith S.serial S.yield [n..n+value]
103{-# INLINE sourceFoldMapWithM #-}
104sourceFoldMapWithM :: Monad m => Int -> Stream m Int
105sourceFoldMapWithM n = S.foldMapWith S.serial (S.yieldM . return) [n..n+value]
107{-# INLINE source #-}
108source :: S.MonadAsync m => Int -> Stream m Int
109source = sourceUnfoldrM
111-------------------------------------------------------------------------------
112-- Elimination
113-------------------------------------------------------------------------------
115{-# INLINE runStream #-}
116runStream :: Monad m => Stream m a -> m ()
117runStream = S.runStream
119toNull = runStream
120uncons s = do
121 r <- S.uncons s
122 case r of
123 Nothing -> return ()
124 Just (_, t) -> uncons t
126{-# INLINE init #-}
127init :: (Monad m, S.IsStream t) => t m a -> m ()
128init s = do
129 t <- S.init s
130 mapM_ S.runStream t
132{-# INLINE tail #-}
133tail :: (Monad m, S.IsStream t) => t m a -> m ()
134tail s = S.tail s >>= mapM_ tail
136nullTail s = do
137 r <- S.null s
138 when (not r) $ S.tail s >>= mapM_ nullTail
140headTail s = do
141 h <- S.head s
142 when (isJust h) $ S.tail s >>= mapM_ headTail
144toList = S.toList
145foldl = S.foldl' (+) 0
146last = S.last
148-------------------------------------------------------------------------------
149-- Transformation
150-------------------------------------------------------------------------------
152{-# INLINE transform #-}
153transform :: Monad m => Stream m a -> m ()
154transform = runStream
156{-# INLINE composeN #-}
157composeN
158 :: Monad m
159 => Int -> (Stream m Int -> Stream m Int) -> Stream m Int -> m ()
160composeN n f =
161 case n of
162 1 -> transform . f
163 2 -> transform . f . f
164 3 -> transform . f . f . f
165 4 -> transform . f . f . f . f
166 _ -> undefined
168{-# INLINE scan #-}
169{-# INLINE map #-}
170{-# INLINE fmap #-}
171{-# INLINE filterEven #-}
172{-# INLINE filterAllOut #-}
173{-# INLINE filterAllIn #-}
174{-# INLINE takeOne #-}
175{-# INLINE takeAll #-}
176{-# INLINE takeWhileTrue #-}
177{-# INLINE dropOne #-}
178{-# INLINE dropAll #-}
179{-# INLINE dropWhileTrue #-}
180{-# INLINE dropWhileFalse #-}
181scan, map, fmap, filterEven, filterAllOut,
182 filterAllIn, takeOne, takeAll, takeWhileTrue, dropAll, dropOne,
183 dropWhileTrue, dropWhileFalse
184 :: Monad m
185 => Int -> Stream m Int -> m ()
187{-# INLINE mapM #-}
188mapM :: S.MonadAsync m => Int -> Stream m Int -> m ()
190scan n = composeN n $ S.scanl' (+) 0
191map n = composeN n $ P.fmap (+1)
192fmap n = composeN n $ P.fmap (+1)
193mapM n = composeN n $ S.mapM return
194filterEven n = composeN n $ S.filter even
195filterAllOut n = composeN n $ S.filter (> maxValue)
196filterAllIn n = composeN n $ S.filter (<= maxValue)
197takeOne n = composeN n $ S.take 1
198takeAll n = composeN n $ S.take maxValue
199takeWhileTrue n = composeN n $ S.takeWhile (<= maxValue)
200dropOne n = composeN n $ S.drop 1
201dropAll n = composeN n $ S.drop maxValue
202dropWhileTrue n = composeN n $ S.dropWhile (<= maxValue)
203dropWhileFalse n = composeN n $ S.dropWhile (<= 1)
205-------------------------------------------------------------------------------
206-- Iteration
207-------------------------------------------------------------------------------
209iterStreamLen, maxIters :: Int
210iterStreamLen = 10
211maxIters = 10000
213{-# INLINE iterateSource #-}
214iterateSource
215 :: S.MonadAsync m
216 => (Stream m Int -> Stream m Int) -> Int -> Int -> Stream m Int
217iterateSource g i n = f i (sourceUnfoldrMN iterStreamLen n)
218 where
219 f (0 :: Int) m = g m
220 f x m = g (f (x P.- 1) m)
222{-# INLINE iterateMapM #-}
223{-# INLINE iterateScan #-}
224{-# INLINE iterateFilterEven #-}
225{-# INLINE iterateTakeAll #-}
226{-# INLINE iterateDropOne #-}
227{-# INLINE iterateDropWhileFalse #-}
228{-# INLINE iterateDropWhileTrue #-}
229iterateMapM, iterateScan, iterateFilterEven, iterateTakeAll, iterateDropOne,
230 iterateDropWhileFalse, iterateDropWhileTrue
231 :: S.MonadAsync m
232 => Int -> Stream m Int
234-- this is quadratic
235iterateScan = iterateSource (S.scanl' (+) 0) (maxIters `div` 10)
236iterateDropWhileFalse = iterateSource (S.dropWhile (> maxValue))
237 (maxIters `div` 10)
239iterateMapM = iterateSource (S.mapM return) maxIters
240iterateFilterEven = iterateSource (S.filter even) maxIters
241iterateTakeAll = iterateSource (S.take maxValue) maxIters
242iterateDropOne = iterateSource (S.drop 1) maxIters
243iterateDropWhileTrue = iterateSource (S.dropWhile (<= maxValue)) maxIters
245-------------------------------------------------------------------------------
246-- Zipping and concat
247-------------------------------------------------------------------------------
249zip src = transform $ S.zipWith (,) src src
250concat _n = return ()
252-------------------------------------------------------------------------------
253-- Mixed Composition
254-------------------------------------------------------------------------------
256{-# INLINE scanMap #-}
257{-# INLINE dropMap #-}
258{-# INLINE dropScan #-}
259{-# INLINE takeDrop #-}
260{-# INLINE takeScan #-}
261{-# INLINE takeMap #-}
262{-# INLINE filterDrop #-}
263{-# INLINE filterTake #-}
264{-# INLINE filterScan #-}
265{-# INLINE filterMap #-}
266scanMap, dropMap, dropScan, takeDrop, takeScan, takeMap, filterDrop,
267 filterTake, filterScan, filterMap
268 :: Monad m => Int -> Stream m Int -> m ()
270scanMap n = composeN n $ S.map (subtract 1) . S.scanl' (+) 0
271dropMap n = composeN n $ S.map (subtract 1) . S.drop 1
272dropScan n = composeN n $ S.scanl' (+) 0 . S.drop 1
273takeDrop n = composeN n $ S.drop 1 . S.take maxValue
274takeScan n = composeN n $ S.scanl' (+) 0 . S.take maxValue
275takeMap n = composeN n $ S.map (subtract 1) . S.take maxValue
276filterDrop n = composeN n $ S.drop 1 . S.filter (<= maxValue)
277filterTake n = composeN n $ S.take maxValue . S.filter (<= maxValue)
278filterScan n = composeN n $ S.scanl' (+) 0 . S.filter (<= maxBound)
279filterMap n = composeN n $ S.map (subtract 1) . S.filter (<= maxValue)