on master help sign in
Add detailed benchmarks for folds

INLINE foldlM'

commit7d577a469b2c61b74a79e6db11a9b3c14377f553 authorHarendra Kumar <harendra.kumar@gmail.com> dateSat 29 Dec 2018, 21:10 (8 years ago) parentaaf8d2c
3 files changed+76−18
benchmark/Linear.hs+40−5 benchmark/LinearOps.hs+31−13 src/Streamly/Prelude.hs+5
benchmark/Linear.hs+40−5
@@ -26,6 +26,14 @@ benchIOSink
2626 => String -> (t IO Int -> IO b) -> Benchmark
2727benchIOSink name f = bench name $ nfIO $ randomRIO (1,1) >>= f . Ops.source
2828
29+-- XXX We should be using sourceUnfoldrM for fair comparison with IO monad, but
30+-- we can't use it as it requires MonadAsync constraint.
31+{-# INLINE benchIdentitySink #-}
32+benchIdentitySink
33+ :: (IsStream t, NFData b)
34+ => String -> (t Identity Int -> Identity b) -> Benchmark
35+benchIdentitySink name f = bench name $ nf (f . Ops.sourceUnfoldr) 1
36+
2937-- | Takes a source, and uses it with a default drain/fold method.
3038{-# INLINE benchIOSrc #-}
3139benchIOSrc
@@ -107,11 +115,38 @@ main =
107115 , benchIOSink "nullHeadTail" Ops.nullHeadTail
108116 , benchIOSink "mapM_" Ops.mapM_
109117 , benchIOSink "toList" Ops.toList
110− , benchIOSink "foldr" Ops.foldr
111− , benchIOSink "foldr1" Ops.foldr1
112− , benchIOSink "foldrM" Ops.foldrM
113− , benchIOSink "foldl'" Ops.foldl'
114− , benchIOSink "foldl1'" Ops.foldl1'
118+
119+ , bgroup "reduce"
120+ [ bgroup "IO"
121+ [ benchIOSink "foldr" Ops.foldrReduce
122+ , benchIOSink "foldr1" Ops.foldr1Reduce
123+ , benchIOSink "foldl'" Ops.foldl'Reduce
124+ , benchIOSink "foldl1'" Ops.foldl1'Reduce
125+ , benchIOSink "foldlM'" Ops.foldlM'Reduce
126+ ]
127+ , bgroup "Identity"
128+ [ benchIdentitySink "foldr" Ops.foldrReduce
129+ , benchIdentitySink "foldr1" Ops.foldr1Reduce
130+ , benchIdentitySink "foldl'" Ops.foldl'Reduce
131+ , benchIdentitySink "foldl1'" Ops.foldl1'Reduce
132+ , benchIdentitySink "foldlM'" Ops.foldlM'Reduce
133+ ]
134+ ]
135+
136+ , bgroup "build"
137+ [ bgroup "IO"
138+ [ benchIOSink "foldr" Ops.foldrBuild
139+ , benchIOSink "foldrM" Ops.foldrMBuild
140+ , benchIOSink "foldl'" Ops.foldl'Build
141+ , benchIOSink "foldlM'" Ops.foldlM'Build
142+ ]
143+ , bgroup "Identity"
144+ [ benchIdentitySink "foldr" Ops.foldrBuild
145+ , benchIdentitySink "foldrM" Ops.foldrMBuild
146+ , benchIdentitySink "foldl'" Ops.foldl'Build
147+ , benchIdentitySink "foldlM'" Ops.foldlM'Build
148+ ]
149+ ]
115150
116151 , benchIOSink "last" Ops.last
117152 , benchIOSink "length" Ops.length
benchmark/LinearOps.hs+31−13
@@ -19,7 +19,8 @@ import Data.Maybe (fromJust)
1919import Prelude
2020 (Monad, Int, (+), ($), (.), return, fmap, even, (>), (<=), (==), (>=),
2121 subtract, undefined, Maybe(..), odd, Bool, not, (>>=), mapM_, curry,
22− maxBound, div, IO, compare, Double, fromIntegral, Integer, (<$>), (<*>))
22+ maxBound, div, IO, compare, Double, fromIntegral, Integer, (<$>),
23+ (<*>), flip)
2324import qualified Prelude as P
2425import qualified Data.Foldable as F
2526import qualified GHC.Exts as GHC
@@ -170,22 +171,32 @@ toList :: Monad m => Stream m Int -> m [Int]
170171{-# INLINE find #-}
171172{-# INLINE findIndex #-}
172173{-# INLINE elemIndex #-}
173−{-# INLINE foldl1' #-}
174−{-# INLINE foldr1 #-}
175−last, minimum, maximum, find, findIndex, elemIndex, foldl1', foldr1
174+{-# INLINE foldl1'Reduce #-}
175+{-# INLINE foldr1Reduce #-}
176+last, minimum, maximum, find, findIndex, elemIndex, foldl1'Reduce, foldr1Reduce
176177 :: Monad m => Stream m Int -> m (Maybe Int)
177178
178179{-# INLINE minimumBy #-}
179180{-# INLINE maximumBy #-}
180181minimumBy, maximumBy :: Monad m => Stream m Int -> m (Maybe Int)
181182
182−{-# INLINE foldl' #-}
183−{-# INLINE foldr #-}
184−{-# INLINE foldrM #-}
183+{-# INLINE foldl'Reduce #-}
184+{-# INLINE foldlM'Reduce #-}
185+{-# INLINE foldrReduce #-}
185186{-# INLINE length #-}
186187{-# INLINE sum #-}
187188{-# INLINE product #-}
188−foldl', foldr, foldrM, length, sum, product :: Monad m => Stream m Int -> m Int
189+foldl'Reduce, foldlM'Reduce, foldrReduce, length, sum, product
190+ :: Monad m
191+ => Stream m Int -> m Int
192+
193+{-# INLINE foldl'Build #-}
194+{-# INLINE foldlM'Build #-}
195+{-# INLINE foldrBuild #-}
196+{-# INLINE foldrMBuild #-}
197+foldrBuild, foldrMBuild, foldl'Build, foldlM'Build
198+ :: Monad m
199+ => Stream m Int -> m [Int]
189200
190201{-# INLINE all #-}
191202{-# INLINE any #-}
@@ -228,11 +239,18 @@ mapM_ :: Monad m => Stream m Int -> m ()
228239mapM_ = S.mapM_ (\_ -> return ())
229240
230241toList = S.toList
231−foldr = S.foldr (+) 0
232−foldr1 = S.foldr1 (+)
233−foldrM = S.foldrM (\a xs -> return $ a + xs) 0
234−foldl' = S.foldl' (+) 0
235−foldl1' = S.foldl1' (+)
242+
243+foldl'Build = S.foldl' (flip (:)) []
244+foldrBuild = S.foldr (:) []
245+foldlM'Build = S.foldlM' (\xs x -> return $ x : xs) []
246+foldrMBuild = S.foldrM (\x xs -> return $ x : xs) []
247+
248+foldrReduce = S.foldr (+) 0
249+foldr1Reduce = S.foldr1 (+)
250+foldl'Reduce = S.foldl' (+) 0
251+foldl1'Reduce = S.foldl1' (+)
252+foldlM'Reduce = S.foldlM' (\xs a -> return $ a + xs) 0
253+
236254last = S.last
237255elem = S.elem maxValue
238256notElem = S.notElem maxValue
src/Streamly/Prelude.hs+5
@@ -809,6 +809,9 @@ foldrM = P.foldrM
809809foldr :: Monad m => (a -> b -> b) -> b -> SerialT m a -> m b
810810foldr = P.foldr
811811
812+-- XXX This seems to be of limited use as it cannot be used to construct
813+-- recursive structures and for reduction foldl1' is better.
814+--
812815-- | Lazy right fold for non-empty streams, using first element as the starting
813816-- value. Returns 'Nothing' if the stream is empty.
814817--
@@ -927,6 +930,7 @@ foldl1' step m = do
927930-- | Like 'foldx', but with a monadic step function.
928931--
929932-- @since 0.2.0
933+{-# INLINE foldxM #-}
930934foldxM :: Monad m => (x -> a -> m x) -> m x -> (x -> m b) -> SerialT m a -> m b
931935foldxM = K.foldxM
932936
@@ -939,6 +943,7 @@ foldlM = foldxM
939943-- | Like 'foldl'' but with a monadic step function.
940944--
941945-- @since 0.2.0
946+{-# INLINE foldlM' #-}
942947foldlM' :: Monad m => (b -> a -> m b) -> b -> SerialT m a -> m b
943948foldlM' step begin m = S.foldlM' step begin $ toStreamS m
944949