on 5cbcd5b help sign in
streamly/benchmark/LinearOps.hs
324 lines 10.0 kB history raw
1-- |
2-- Module : BenchmarkOps
3-- Copyright : (c) 2018 Harendra Kumar
4--
5-- License : MIT
6-- Maintainer : harendra.kumar@gmail.com
8{-# LANGUAGE CPP #-}
9{-# LANGUAGE FlexibleContexts #-}
11module LinearOps where
13import Control.Monad (when)
14import Data.Maybe (fromJust)
15import Prelude
16 (Monad, Int, (+), ($), (.), return, fmap, even, (>), (<=), (==), (<=),
17 subtract, undefined, Maybe(..), odd, Bool, not, (>>=), mapM_, curry)
19import qualified Streamly as S
20import qualified Streamly.Prelude as S
22value, maxValue :: Int
23#ifdef LINEAR_ASYNC
24value = 10000
25#else
26value = 100000
27#endif
28maxValue = value + 1
30-------------------------------------------------------------------------------
31-- Benchmark ops
32-------------------------------------------------------------------------------
34-------------------------------------------------------------------------------
35-- Stream generation and elimination
36-------------------------------------------------------------------------------
38type Stream m a = S.SerialT m a
40{-# INLINE source #-}
41source :: (S.MonadAsync m, S.IsStream t) => Int -> t m Int
42source n = S.serially $ sourceUnfoldrM n
43-- source n = S.serially $ sourceFromList n
45{-# INLINE sourceFromList #-}
46sourceFromList :: (Monad m, S.IsStream t) => Int -> t m Int
47sourceFromList n = S.fromList [n..n+value]
49{-# INLINE sourceFromListM #-}
50sourceFromListM :: (S.MonadAsync m, S.IsStream t) => Int -> t m Int
51sourceFromListM n = S.fromListM (Prelude.fmap return [n..n+value])
53{-# INLINE sourceFromFoldable #-}
54sourceFromFoldable :: S.IsStream t => Int -> t m Int
55sourceFromFoldable n = S.fromFoldable [n..n+value]
57{-# INLINE sourceFromFoldableM #-}
58sourceFromFoldableM :: (S.IsStream t, S.MonadAsync m) => Int -> t m Int
59sourceFromFoldableM n = S.fromFoldableM (Prelude.fmap return [n..n+value])
61{-# INLINE sourceFoldMapWith #-}
62sourceFoldMapWith :: (S.IsStream t, S.Semigroup (t m Int))
63 => Int -> t m Int
64sourceFoldMapWith n = S.foldMapWith (S.<>) S.yield [n..n+value]
66{-# INLINE sourceFoldMapWithM #-}
67sourceFoldMapWithM :: (S.IsStream t, Monad m, S.Semigroup (t m Int))
68 => Int -> t m Int
69sourceFoldMapWithM n = S.foldMapWith (S.<>) (S.yieldM . return) [n..n+value]
71{-# INLINE sourceUnfoldr #-}
72sourceUnfoldr :: (Monad m, S.IsStream t) => Int -> t m Int
73sourceUnfoldr n = S.unfoldr step n
74 where
75 step cnt =
76 if cnt > n + value
77 then Nothing
78 else Just (cnt, cnt + 1)
80{-# INLINE sourceUnfoldrM #-}
81sourceUnfoldrM :: (S.IsStream t, S.MonadAsync m) => Int -> t m Int
82sourceUnfoldrM n = S.unfoldrM step n
83 where
84 step cnt =
85 if cnt > n + value
86 then return Nothing
87 else return (Just (cnt, cnt + 1))
89{-# INLINE sourceUnfoldrMN #-}
90sourceUnfoldrMN :: (S.IsStream t, S.MonadAsync m) => Int -> Int -> t m Int
91sourceUnfoldrMN m n = S.unfoldrM step n
92 where
93 step cnt =
94 if cnt > n + m
95 then return Nothing
96 else return (Just (cnt, cnt + 1))
98{-# INLINE sourceUnfoldrMAction #-}
99sourceUnfoldrMAction :: (S.IsStream t, S.MonadAsync m) => Int -> t m (m Int)
100sourceUnfoldrMAction n = S.serially $ S.unfoldrM step n
101 where
102 step cnt =
103 if cnt > n + value
104 then return Nothing
105 else return (Just (return cnt, cnt + 1))
107-------------------------------------------------------------------------------
108-- Elimination
109-------------------------------------------------------------------------------
111{-# INLINE runStream #-}
112runStream :: Monad m => Stream m a -> m ()
113runStream = S.runStream
115{-# INLINE toList #-}
116{-# INLINE foldr #-}
117{-# INLINE foldrM #-}
118toList, foldr, foldrM :: Monad m => Stream m Int -> m [Int]
120{-# INLINE last #-}
121{-# INLINE maximum #-}
122{-# INLINE minimum #-}
123{-# INLINE find #-}
124{-# INLINE findIndex #-}
125{-# INLINE elemIndex #-}
126{-# INLINE foldl1' #-}
127{-# INLINE foldr1 #-}
128last, minimum, maximum, find, findIndex, elemIndex, foldl1', foldr1 :: Monad m => Stream m Int -> m (Maybe Int)
130{-# INLINE foldl' #-}
131{-# INLINE length #-}
132{-# INLINE sum #-}
133{-# INLINE product #-}
134foldl', length, sum, product :: Monad m => Stream m Int -> m Int
136{-# INLINE all #-}
137{-# INLINE any #-}
138{-# INLINE and #-}
139{-# INLINE or #-}
140{-# INLINE elem #-}
141{-# INLINE notElem #-}
142elem, notElem, all, any, and, or :: Monad m => Stream m Int -> m Bool
144{-# INLINE toNull #-}
145toNull :: Monad m => (t m Int -> S.SerialT m Int) -> t m Int -> m ()
146toNull t = runStream . t
148{-# INLINE uncons #-}
149uncons :: Monad m => Stream m Int -> m ()
150uncons s = do
151 r <- S.uncons s
152 case r of
153 Nothing -> return ()
154 Just (_, t) -> uncons t
156{-# INLINE init #-}
157init :: Monad m => Stream m a -> m ()
158init s = S.init s >>= Prelude.mapM_ S.runStream
160{-# INLINE tail #-}
161tail :: Monad m => Stream m a -> m ()
162tail s = S.tail s >>= Prelude.mapM_ tail
164{-# INLINE nullHeadTail #-}
165nullHeadTail :: Monad m => Stream m Int -> m ()
166nullHeadTail s = do
167 r <- S.null s
168 when (not r) $ do
169 _ <- S.head s
170 S.tail s >>= Prelude.mapM_ nullHeadTail
172mapM_ = S.mapM_ (\_ -> return ())
173toList = S.toList
174foldr = S.foldr (:) []
175foldr1 = S.foldr1 (+)
176foldrM = S.foldrM (\a xs -> return (a : xs)) []
177foldl' = S.foldl' (+) 0
178foldl1' = S.foldl1' (+)
179last = S.last
180elem = S.elem maxValue
181notElem = S.notElem maxValue
182length = S.length
183all = S.all (<= maxValue)
184any = S.any (> maxValue)
185and = S.and . S.map (<= maxValue)
186or = S.or . S.map (> maxValue)
187find = S.find (== maxValue)
188findIndex = S.findIndex (== maxValue)
189elemIndex = S.elemIndex maxValue
190maximum = S.maximum
191minimum = S.minimum
192sum = S.sum
193product = S.product
195-------------------------------------------------------------------------------
196-- Transformation
197-------------------------------------------------------------------------------
199{-# INLINE transform #-}
200transform :: Monad m => Stream m a -> m ()
201transform = runStream
203{-# INLINE scan #-}
204{-# INLINE mapM_ #-}
205{-# INLINE map #-}
206{-# INLINE fmap #-}
207{-# INLINE mapMaybe #-}
208{-# INLINE filterEven #-}
209{-# INLINE filterAllOut #-}
210{-# INLINE filterAllIn #-}
211{-# INLINE takeOne #-}
212{-# INLINE takeAll #-}
213{-# INLINE takeWhileTrue #-}
214{-# INLINE takeWhileMTrue #-}
215{-# INLINE dropAll #-}
216{-# INLINE dropWhileTrue #-}
217{-# INLINE dropWhileMTrue #-}
218{-# INLINE findIndices #-}
219{-# INLINE elemIndices #-}
220scan, mapM_, map, fmap, mapMaybe, filterEven, filterAllOut,
221 filterAllIn, takeOne, takeAll, takeWhileTrue, takeWhileMTrue, dropAll,
222 dropWhileTrue, dropWhileMTrue,
223 findIndices, elemIndices
224 :: Monad m
225 => Stream m Int -> m ()
227{-# INLINE mapMaybeM #-}
228mapMaybeM :: S.MonadAsync m => Stream m Int -> m ()
230{-# INLINE mapM #-}
231mapM :: (S.IsStream t, S.MonadAsync m)
232 => (t m Int -> S.SerialT m Int) -> t m Int -> m ()
234{-# INLINE sequence #-}
235sequence :: (S.IsStream t, S.MonadAsync m)
236 => (t m Int -> S.SerialT m Int) -> t m (m Int) -> m ()
238scan = transform . S.scanl' (+) 0
239fmap = transform . Prelude.fmap (+1)
240map = transform . S.map (+1)
241mapM t = transform . t . S.mapM return
242mapMaybe = transform . S.mapMaybe
243 (\x -> if Prelude.odd x then Nothing else Just ())
244mapMaybeM = transform . S.mapMaybeM
245 (\x -> if Prelude.odd x then return Nothing else return $ Just ())
246sequence t = transform . t . S.sequence
247filterEven = transform . S.filter even
248filterAllOut = transform . S.filter (> maxValue)
249filterAllIn = transform . S.filter (<= maxValue)
250takeOne = transform . S.take 1
251takeAll = transform . S.take maxValue
252takeWhileTrue = transform . S.takeWhile (<= maxValue)
253takeWhileMTrue = transform . S.takeWhileM (return . (<= maxValue))
254dropAll = transform . S.drop maxValue
255dropWhileTrue = transform . S.dropWhile (<= maxValue)
256dropWhileMTrue = transform . S.dropWhileM (return . (<= maxValue))
257findIndices = transform . S.findIndices (== maxValue)
258elemIndices = transform . S.elemIndices maxValue
260-------------------------------------------------------------------------------
261-- Zipping and concat
262-------------------------------------------------------------------------------
264{-# INLINE zip #-}
265{-# INLINE zipM #-}
266{-# INLINE concat #-}
267zip, zipM, concat :: Monad m => Stream m Int -> m ()
269{-# INLINE zipAsync #-}
270{-# INLINE zipAsyncM #-}
271zipAsync, zipAsyncM :: S.MonadAsync m => Stream m Int -> m ()
273zip src = do
274 r <- S.tail src
275 let src1 = fromJust r
276 transform (S.zipWith (,) src src1)
277zipM src = do
278 r <- S.tail src
279 let src1 = fromJust r
280 transform (S.zipWithM (curry return) src src1)
281zipAsync src = do
282 r <- S.tail src
283 let src1 = fromJust r
284 transform (S.zipAsyncWith (,) src src1)
285zipAsyncM src = do
286 r <- S.tail src
287 let src1 = fromJust r
288 transform (S.zipAsyncWithM (curry return) src src1)
289concat _n = return ()
291-------------------------------------------------------------------------------
292-- Composition
293-------------------------------------------------------------------------------
295{-# INLINE compose #-}
296compose :: Monad m => (Stream m Int -> Stream m Int) -> Stream m Int -> m ()
297compose f = transform . f . f . f . f
299{-# INLINE composeMapM #-}
300{-# INLINE composeAllInFilters #-}
301{-# INLINE composeAllOutFilters #-}
302{-# INLINE composeMapAllInFilter #-}
303composeAllInFilters, composeAllOutFilters,
304 composeMapAllInFilter
305 :: Monad m
306 => Stream m Int -> m ()
307composeMapM :: S.MonadAsync m => Stream m Int -> m ()
309composeMapM = compose (S.mapM return)
310composeAllInFilters = compose (S.filter (<= maxValue))
311composeAllOutFilters = compose (S.filter (> maxValue))
312composeMapAllInFilter =
313 compose (S.filter (<= maxValue) . Prelude.fmap (subtract 1))
315{-# INLINABLE composeScaling #-}
316composeScaling :: Monad m => Int -> Stream m Int -> m ()
317composeScaling m =
318 case m of
319 1 -> transform . f
320 2 -> transform . f . f
321 3 -> transform . f . f . f
322 4 -> transform . f . f . f . f
323 _ -> undefined
324 where f = S.filter (<= maxValue)