on bf4e5d8 help sign in
streamly/benchmark/StreamDOps.hs
269 lines 8.5 kB history raw
1-- |
2-- Module : StreamDOps
3-- Copyright : (c) 2018 Harendra Kumar
4--
5-- License : BSD3
6-- Maintainer : harendra.kumar@gmail.com
8{-# LANGUAGE FlexibleContexts #-}
9{-# LANGUAGE ScopedTypeVariables #-}
11module StreamDOps 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, fmap, odd)
19import qualified Prelude as P
21import qualified Streamly.Streams.StreamD as S
23value, maxValue :: Int
24value = 100000
25maxValue = value + 1000
27-------------------------------------------------------------------------------
28-- Benchmark ops
29-------------------------------------------------------------------------------
31{-# INLINE uncons #-}
32{-# INLINE nullTail #-}
33{-# INLINE headTail #-}
34{-# INLINE zip #-}
35{-
36{-# INLINE concat #-}
37-}
38uncons, nullTail, headTail, zip
39 -- 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{-# INLINE toNull #-}
51toNull :: Monad m => Stream m Int -> m ()
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 sourceUnfoldrMN #-}
69sourceUnfoldrMN :: Monad m => Int -> Int -> Stream m Int
70sourceUnfoldrMN m n = S.unfoldrM step n
71 where
72 step cnt =
73 if cnt > n + m
74 then return Nothing
75 else return (Just (cnt, cnt + 1))
77{-# INLINE sourceUnfoldrM #-}
78sourceUnfoldrM :: Monad m => Int -> Stream m Int
79sourceUnfoldrM n = S.unfoldrM step n
80 where
81 step cnt =
82 if cnt > n + value
83 then return Nothing
84 else return (Just (cnt, cnt + 1))
86{-# INLINE sourceFromEnum #-}
87sourceFromEnum :: Monad m => Int -> Stream m Int
88sourceFromEnum n = S.enumFromStepN n 1 value
90{-# INLINE sourceFromList #-}
91sourceFromList :: Monad m => Int -> Stream m Int
92sourceFromList n = S.fromList [n..n+value]
94{-# INLINE source #-}
95source :: Monad m => Int -> Stream m Int
96source = sourceUnfoldrM
98-------------------------------------------------------------------------------
99-- Elimination
100-------------------------------------------------------------------------------
102{-# INLINE runStream #-}
103runStream :: Monad m => Stream m a -> m ()
104runStream = S.runStream
106toNull = runStream
108uncons s = do
109 r <- S.uncons s
110 case r of
111 Nothing -> return ()
112 Just (_, t) -> uncons t
114{-# INLINE tail #-}
115tail :: Monad m => Stream m a -> m ()
116tail s = S.tail s >>= mapM_ tail
118nullTail s = do
119 r <- S.null s
120 when (not r) $ S.tail s >>= mapM_ nullTail
122headTail s = do
123 h <- S.head s
124 when (isJust h) $ S.tail s >>= mapM_ headTail
126toList = S.toList
127foldl = S.foldl' (+) 0
128last = S.last
130-------------------------------------------------------------------------------
131-- Transformation
132-------------------------------------------------------------------------------
134{-# INLINE transform #-}
135transform :: Monad m => Stream m a -> m ()
136transform = runStream
138{-# INLINE composeN #-}
139composeN
140 :: Monad m
141 => Int -> (Stream m Int -> Stream m Int) -> Stream m Int -> m ()
142composeN n f =
143 case n of
144 1 -> transform . f
145 2 -> transform . f . f
146 3 -> transform . f . f . f
147 4 -> transform . f . f . f . f
148 _ -> undefined
150{-# INLINE scan #-}
151{-# INLINE map #-}
152{-# INLINE fmap #-}
153{-# INLINE mapM #-}
154{-# INLINE mapMaybe #-}
155{-# INLINE mapMaybeM #-}
156{-# INLINE filterEven #-}
157{-# INLINE filterAllOut #-}
158{-# INLINE filterAllIn #-}
159{-# INLINE takeOne #-}
160{-# INLINE takeAll #-}
161{-# INLINE takeWhileTrue #-}
162{-# INLINE takeWhileMTrue #-}
163{-# INLINE dropOne #-}
164{-# INLINE dropAll #-}
165{-# INLINE dropWhileTrue #-}
166{-# INLINE dropWhileMTrue #-}
167{-# INLINE dropWhileFalse #-}
168scan, map, fmap, mapM, mapMaybe, mapMaybeM, filterEven, filterAllOut,
169 filterAllIn, takeOne, takeAll, takeWhileTrue, takeWhileMTrue, dropOne,
170 dropAll, dropWhileTrue, dropWhileMTrue, dropWhileFalse
171 :: Monad m
172 => Int -> Stream m Int -> m ()
174scan n = composeN n $ S.scanl' (+) 0
175fmap n = composeN n $ Prelude.fmap (+1)
176map n = composeN n $ S.map (+1)
177mapM n = composeN n $ S.mapM return
178mapMaybe n = composeN n $ S.mapMaybe
179 (\x -> if Prelude.odd x then Nothing else Just x)
180mapMaybeM n = composeN n $ S.mapMaybeM
181 (\x -> if Prelude.odd x then return Nothing else return $ Just x)
182filterEven n = composeN n $ S.filter even
183filterAllOut n = composeN n $ S.filter (> maxValue)
184filterAllIn n = composeN n $ S.filter (<= maxValue)
185takeOne n = composeN n $ S.take 1
186takeAll n = composeN n $ S.take maxValue
187takeWhileTrue n = composeN n $ S.takeWhile (<= maxValue)
188takeWhileMTrue n = composeN n $ S.takeWhileM (return . (<= maxValue))
189dropOne n = composeN n $ S.drop 1
190dropAll n = composeN n $ S.drop maxValue
191dropWhileTrue n = composeN n $ S.dropWhile (<= maxValue)
192dropWhileMTrue n = composeN n $ S.dropWhileM (return . (<= maxValue))
193dropWhileFalse n = composeN n $ S.dropWhile (> maxValue)
195-------------------------------------------------------------------------------
196-- Iteration
197-------------------------------------------------------------------------------
199iterStreamLen, maxIters :: Int
200iterStreamLen = 10
201maxIters = 10000
203{-# INLINE iterateSource #-}
204iterateSource
205 :: Monad m
206 => (Stream m Int -> Stream m Int) -> Int -> Int -> Stream m Int
207iterateSource g i n = f i (sourceUnfoldrMN iterStreamLen n)
208 where
209 f (0 :: Int) m = g m
210 f x m = g (f (x P.- 1) m)
212{-# INLINE iterateMapM #-}
213{-# INLINE iterateScan #-}
214{-# INLINE iterateFilterEven #-}
215{-# INLINE iterateTakeAll #-}
216{-# INLINE iterateDropOne #-}
217{-# INLINE iterateDropWhileFalse #-}
218{-# INLINE iterateDropWhileTrue #-}
219iterateMapM, iterateScan, iterateFilterEven, iterateTakeAll, iterateDropOne,
220 iterateDropWhileFalse, iterateDropWhileTrue
221 :: Monad m
222 => Int -> Stream m Int
224-- this is quadratic
225iterateScan = iterateSource (S.scanl' (+) 0) (maxIters `div` 10)
226iterateDropWhileFalse = iterateSource (S.dropWhile (> maxValue))
227 (maxIters `div` 10)
229iterateMapM = iterateSource (S.mapM return) maxIters
230iterateFilterEven = iterateSource (S.filter even) maxIters
231iterateTakeAll = iterateSource (S.take maxValue) maxIters
232iterateDropOne = iterateSource (S.drop 1) maxIters
233iterateDropWhileTrue = iterateSource (S.dropWhile (<= maxValue)) maxIters
235-------------------------------------------------------------------------------
236-- Zipping and concat
237-------------------------------------------------------------------------------
239zip src = transform $ S.zipWith (,) src src
240-- concat _n = return ()
242-------------------------------------------------------------------------------
243-- Mixed Composition
244-------------------------------------------------------------------------------
246{-# INLINE scanMap #-}
247{-# INLINE dropMap #-}
248{-# INLINE dropScan #-}
249{-# INLINE takeDrop #-}
250{-# INLINE takeScan #-}
251{-# INLINE takeMap #-}
252{-# INLINE filterDrop #-}
253{-# INLINE filterTake #-}
254{-# INLINE filterScan #-}
255{-# INLINE filterMap #-}
256scanMap, dropMap, dropScan, takeDrop, takeScan, takeMap, filterDrop,
257 filterTake, filterScan, filterMap
258 :: Monad m => Int -> Stream m Int -> m ()
260scanMap n = composeN n $ S.map (subtract 1) . S.scanl' (+) 0
261dropMap n = composeN n $ S.map (subtract 1) . S.drop 1
262dropScan n = composeN n $ S.scanl' (+) 0 . S.drop 1
263takeDrop n = composeN n $ S.drop 1 . S.take maxValue
264takeScan n = composeN n $ S.scanl' (+) 0 . S.take maxValue
265takeMap n = composeN n $ S.map (subtract 1) . S.take maxValue
266filterDrop n = composeN n $ S.drop 1 . S.filter (<= maxValue)
267filterTake n = composeN n $ S.take maxValue . S.filter (<= maxValue)
268filterScan n = composeN n $ S.scanl' (+) 0 . S.filter (<= maxBound)
269filterMap n = composeN n $ S.map (subtract 1) . S.filter (<= maxValue)