on master help sign in
Add transformation/filtering/mixed composition benchmarks
commit819786eca98a17af9124dfba457bb7a31ff715ca authorHarendra Kumar <harendra.kumar@gmail.com> dateMon 29 Oct 2018, 00:21 (8 years ago) parent1ddd81b
4 files changed+172−110
benchmark/Chart.hs+36−19 benchmark/Linear.hs+53−30 benchmark/LinearAsync.hs+4−4 benchmark/LinearOps.hs+79−57
benchmark/Chart.hs+36−19
@@ -85,34 +85,51 @@ ignoringErr a = catch a (\(ErrorCall err :: ErrorCall) ->
8585
8686makeLinearGraphs :: Config -> String -> IO ()
8787makeLinearGraphs cfg inputFile = do
88− ignoringErr $ graph inputFile "operations" $ cfg
89− { title = Just "Streamly operations"
90− , classifyBenchmark = \b ->
91− if not ("serially/" `isPrefixOf` b)
92− || "/generation" `isInfixOf` b
93− || "/compose" `isInfixOf` b
94− || "/concat" `isSuffixOf` b
95− then Nothing
96− else Just ("Streamly", last $ splitOn "/" b)
88+ ignoringErr $ graph inputFile "generation" $ cfg
89+ { title = Just "Generation"
90+ , classifyBenchmark =
91+ fmap ("Streamly",) . stripPrefix "serially/generation/"
9792 }
9893
99− ignoringErr $ graph inputFile "generation" $ cfg
100− { title = Just "Stream generation"
94+ ignoringErr $ graph inputFile "elimination" $ cfg
95+ { title = Just "Elimination"
96+ , classifyBenchmark =
97+ fmap ("Streamly",) . stripPrefix "serially/elimination/"
98+ }
99+
100+ ignoringErr $ graph inputFile "transformation-zip" $ cfg
101+ { title = Just "Transformation & Zip"
101102 , classifyBenchmark = \b ->
102− if "serially/generation" `isPrefixOf` b
103+ if "serially/transformation/" `isPrefixOf` b
104+ || "serially/zip" `isPrefixOf` b
103105 then Just ("Streamly", last $ splitOn "/" b)
104106 else Nothing
105107 }
106108
107− ignoringErr $ graph inputFile "composition" $ cfg
108− { title = Just "Streamly composition performance"
109− , classifyBenchmark = fmap ("Streamly",) . stripPrefix "serially/compose/"
109+ ignoringErr $ graph inputFile "filtering" $ cfg
110+ { title = Just "Filtering"
111+ , classifyBenchmark =
112+ fmap ("Streamly",) . stripPrefix "serially/filtering/"
113+ }
114+
115+ ignoringErr $ graph inputFile "composed-transformation" $ cfg
116+ { title = Just "Composed Transformation"
117+ , classifyBenchmark =
118+ fmap ("Streamly",) . stripPrefix "serially/transformationN/"
119+ }
120+
121+ ignoringErr $ graph inputFile "composed-filtering"
122+ $ cfg
123+ { title = Just "Composed Filtering"
124+ , classifyBenchmark =
125+ fmap ("Streamly",) . stripPrefix "serially/filteringN/"
110126 }
111127
112− ignoringErr $ graph inputFile "composition-scaling"
128+ ignoringErr $ graph inputFile "composed-mixed"
113129 $ cfg
114− { title = Just "Streamly composition scaling"
115− , classifyBenchmark = fmap ("Streamly",) . stripPrefix "serially/compose-"
130+ { title = Just "Composed Mixed"
131+ , classifyBenchmark =
132+ fmap ("Streamly",) . stripPrefix "serially/composed/"
116133 }
117134
118135------------------------------------------------------------------------------
@@ -121,7 +138,7 @@ makeLinearGraphs cfg inputFile = do
121138
122139makeNestedGraphs :: Config -> String -> IO ()
123140makeNestedGraphs cfg inputFile =
124− ignoringErr $ graph inputFile "nested-serial-diff" $ cfg
141+ ignoringErr $ graph inputFile "nested-serial" $ cfg
125142 { title = Just "Nested serial"
126143 , classifyBenchmark = \b ->
127144 let ls = splitOn "/" b
benchmark/Linear.hs+53−30
@@ -84,43 +84,66 @@ main =
8484 , benchIO "product" Ops.product
8585 ]
8686 , bgroup "transformation"
87− [ benchIO "scan" Ops.scan
88− , benchIO "map" Ops.map
89− , benchIO "fmap" Ops.fmap
90− , benchIO "mapM" (Ops.mapM serially)
91− , benchIO "mapMaybe" Ops.mapMaybe
92− , benchIO "mapMaybeM" Ops.mapMaybeM
87+ [ benchIO "scan" (Ops.scan 1)
88+ , benchIO "map" (Ops.map 1)
89+ , benchIO "fmap" (Ops.fmap 1)
90+ , benchIO "mapM" (Ops.mapM serially 1)
91+ , benchIO "mapMaybe" (Ops.mapMaybe 1)
92+ , benchIO "mapMaybeM" (Ops.mapMaybeM 1)
9393 , bench "sequence" $ nfIO $ randomRIO (1,1000) >>= \n ->
9494 Ops.sequence serially (Ops.sourceUnfoldrMAction n)
95− , benchIO "findIndices" Ops.findIndices
96− , benchIO "elemIndices" Ops.elemIndices
95+ , benchIO "findIndices" (Ops.findIndices 1)
96+ , benchIO "elemIndices" (Ops.elemIndices 1)
97+ -- , benchIO "concat" Ops.concat
98+ ]
99+ , bgroup "transformationN"
100+ [ benchIO "scan" (Ops.scan 4)
101+ , benchIO "map" (Ops.map 4)
102+ , benchIO "fmap" (Ops.fmap 4)
103+ , benchIO "mapM" (Ops.mapM serially 4)
104+ , benchIO "mapMaybe" (Ops.mapMaybe 4)
105+ , benchIO "mapMaybeM" (Ops.mapMaybeM 4)
106+ -- , bench "sequence" $ nfIO $ randomRIO (1,1000) >>= \n ->
107+ -- Ops.sequence serially (Ops.sourceUnfoldrMAction n)
108+ , benchIO "findIndices" (Ops.findIndices 4)
109+ , benchIO "elemIndices" (Ops.elemIndices 4)
97110 -- , benchIO "concat" Ops.concat
98111 ]
99112 , bgroup "filtering"
100− [ benchIO "filter-even" Ops.filterEven
101− , benchIO "filter-all-out" Ops.filterAllOut
102− , benchIO "filter-all-in" Ops.filterAllIn
103− , benchIO "take-all" Ops.takeAll
104− , benchIO "takeWhile-true" Ops.takeWhileTrue
105− , benchIO "takeWhileM-true" Ops.takeWhileMTrue
106− , benchIO "drop-all" Ops.dropAll
107− , benchIO "dropWhile-true" Ops.dropWhileTrue
108− , benchIO "dropWhileM-true" Ops.dropWhileMTrue
113+ [ benchIO "filter-even" (Ops.filterEven 1)
114+ , benchIO "filter-all-out" (Ops.filterAllOut 1)
115+ , benchIO "filter-all-in" (Ops.filterAllIn 1)
116+ , benchIO "take-all" (Ops.takeAll 1)
117+ , benchIO "takeWhile-true" (Ops.takeWhileTrue 1)
118+ , benchIO "takeWhileM-true" (Ops.takeWhileMTrue 1)
119+ , benchIO "drop-all" (Ops.dropAll 1)
120+ , benchIO "dropWhile-true" (Ops.dropWhileTrue 1)
121+ , benchIO "dropWhileM-true" (Ops.dropWhileMTrue 1)
122+ ]
123+ , bgroup "filteringN"
124+ [ benchIO "filter-even" (Ops.filterEven 4)
125+ , benchIO "filter-all-out" (Ops.filterAllOut 4)
126+ , benchIO "filter-all-in" (Ops.filterAllIn 4)
127+ , benchIO "take-all" (Ops.takeAll 4)
128+ , benchIO "takeWhile-true" (Ops.takeWhileTrue 4)
129+ , benchIO "takeWhileM-true" (Ops.takeWhileMTrue 4)
130+ , benchIO "drop-all" (Ops.dropAll 4)
131+ , benchIO "dropWhile-true" (Ops.dropWhileTrue 4)
132+ , benchIO "dropWhileM-true" (Ops.dropWhileMTrue 4)
109133 ]
110134 , benchIO "zip" Ops.zip
111135 , benchIO "zipM" Ops.zipM
112− , bgroup "compose"
113− [ benchIO "mapM" Ops.composeMapM
114− , benchIO "map-with-all-in-filter" Ops.composeMapAllInFilter
115− , benchIO "all-in-filters" Ops.composeAllInFilters
116− , benchIO "all-out-filters" Ops.composeAllOutFilters
117− ]
118− -- Scaling with same operation in sequence
119− , bgroup "compose-scaling"
120− [ benchIO "1" $ Ops.composeScaling 1
121− , benchIO "2" $ Ops.composeScaling 2
122− , benchIO "3" $ Ops.composeScaling 3
123− , benchIO "4" $ Ops.composeScaling 4
124− ]
136+ , bgroup "composed"
137+ [ benchIO "scan-map" (Ops.scanMap 4)
138+ , benchIO "drop-map" (Ops.dropMap 4)
139+ , benchIO "drop-scan" (Ops.dropScan 4)
140+ , benchIO "take-drop" (Ops.takeDrop 4)
141+ , benchIO "take-scan" (Ops.takeScan 4)
142+ , benchIO "take-map" (Ops.takeMap 4)
143+ , benchIO "filter-drop" (Ops.filterDrop 4)
144+ , benchIO "filter-take" (Ops.filterTake 4)
145+ , benchIO "filter-scan" (Ops.filterScan 4)
146+ , benchIO "filter-map" (Ops.filterMap 4)
125147 ]
126148 ]
149+ ]
benchmark/LinearAsync.hs+4−4
@@ -46,7 +46,7 @@ main =
4646 , benchSrcIO asyncly "fromFoldableM" Ops.sourceFromFoldableM
4747 -- , benchSrcIO asyncly "foldMapWith" Ops.sourceFoldMapWith
4848 , benchSrcIO asyncly "foldMapWithM" Ops.sourceFoldMapWithM
49− , benchIO "mapM" $ Ops.mapM asyncly
49+ , benchIO "mapM" $ Ops.mapM asyncly 1
5050 , benchSrcIO asyncly "unfoldrM maxThreads 1"
5151 (maxThreads 1 . Ops.sourceUnfoldrM)
5252 , benchSrcIO asyncly "unfoldrM maxBuffer 1 (1000 ops)"
@@ -59,7 +59,7 @@ main =
5959 , benchSrcIO wAsyncly "fromFoldableM" Ops.sourceFromFoldableM
6060 -- , benchSrcIO wAsyncly "foldMapWith" Ops.sourceFoldMapWith
6161 , benchSrcIO wAsyncly "foldMapWithM" Ops.sourceFoldMapWithM
62− , benchIO "mapM" $ Ops.mapM wAsyncly
62+ , benchIO "mapM" $ Ops.mapM wAsyncly 1
6363 ]
6464 -- unfoldr and fromFoldable are always serial and thereofore the same for
6565 -- all stream types.
@@ -69,7 +69,7 @@ main =
6969 , benchSrcIO aheadly "fromFoldableM" Ops.sourceFromFoldableM
7070 -- , benchSrcIO aheadly "foldMapWith" Ops.sourceFoldMapWith
7171 , benchSrcIO aheadly "foldMapWithM" Ops.sourceFoldMapWithM
72− , benchIO "mapM" $ Ops.mapM aheadly
72+ , benchIO "mapM" $ Ops.mapM aheadly 1
7373 , benchSrcIO aheadly "unfoldrM maxThreads 1"
7474 (maxThreads 1 . Ops.sourceUnfoldrM)
7575 , benchSrcIO aheadly "unfoldrM maxBuffer 1 (1000 ops)"
@@ -84,7 +84,7 @@ main =
8484 , benchSrcIO parallely "fromFoldableM" Ops.sourceFromFoldableM
8585 -- , benchSrcIO parallely "foldMapWith" Ops.sourceFoldMapWith
8686 , benchSrcIO parallely "foldMapWithM" Ops.sourceFoldMapWithM
87− , benchIO "mapM" $ Ops.mapM parallely
87+ , benchIO "mapM" $ Ops.mapM parallely 1
8888 -- Zip has only one parallel flavor
8989 , benchIO "zip" Ops.zipAsync
9090 , benchIO "zipM" Ops.zipAsyncM
benchmark/LinearOps.hs+79−57
@@ -14,7 +14,8 @@ import Control.Monad (when)
1414import Data.Maybe (fromJust)
1515import Prelude
1616 (Monad, Int, (+), ($), (.), return, fmap, even, (>), (<=), (==), (<=),
17− subtract, undefined, Maybe(..), odd, Bool, not, (>>=), mapM_, curry)
17+ subtract, undefined, Maybe(..), odd, Bool, not, (>>=), mapM_, curry,
18+ maxBound)
1819
1920import qualified Streamly as S
2021import qualified Streamly.Prelude as S
@@ -169,7 +170,10 @@ nullHeadTail s = do
169170 _ <- S.head s
170171 S.tail s >>= Prelude.mapM_ nullHeadTail
171172
173+{-# INLINE mapM_ #-}
174+mapM_ :: Monad m => Stream m Int -> m ()
172175mapM_ = S.mapM_ (\_ -> return ())
176+
173177toList = S.toList
174178foldr = S.foldr (:) []
175179foldr1 = S.foldr1 (+)
@@ -200,8 +204,32 @@ product = S.product
200204transform :: Monad m => Stream m a -> m ()
201205transform = runStream
202206
207+{-# INLINE composeN #-}
208+composeN
209+ :: Monad m
210+ => Int -> (Stream m Int -> Stream m Int) -> Stream m Int -> m ()
211+composeN n f =
212+ case n of
213+ 1 -> transform . f
214+ 2 -> transform . f . f
215+ 3 -> transform . f . f . f
216+ 4 -> transform . f . f . f . f
217+ _ -> undefined
218+
219+-- polymorphic stream version of composeN
220+{-# INLINE composeN' #-}
221+composeN'
222+ :: (S.IsStream t, Monad m)
223+ => Int -> (t m Int -> Stream m Int) -> t m Int -> m ()
224+composeN' n f =
225+ case n of
226+ 1 -> transform . f
227+ 2 -> transform . f . S.adapt . f
228+ 3 -> transform . f . S.adapt . f . S.adapt . f
229+ 4 -> transform . f . S.adapt . f . S.adapt . f . S.adapt . f
230+ _ -> undefined
231+
203232{-# INLINE scan #-}
204−{-# INLINE mapM_ #-}
205233{-# INLINE map #-}
206234{-# INLINE fmap #-}
207235{-# INLINE mapMaybe #-}
@@ -217,45 +245,45 @@ transform = runStream
217245{-# INLINE dropWhileMTrue #-}
218246{-# INLINE findIndices #-}
219247{-# INLINE elemIndices #-}
220−scan, mapM_, map, fmap, mapMaybe, filterEven, filterAllOut,
248+scan, map, fmap, mapMaybe, filterEven, filterAllOut,
221249 filterAllIn, takeOne, takeAll, takeWhileTrue, takeWhileMTrue, dropAll,
222250 dropWhileTrue, dropWhileMTrue,
223251 findIndices, elemIndices
224252 :: Monad m
225− => Stream m Int -> m ()
253+ => Int -> Stream m Int -> m ()
226254
227255{-# INLINE mapMaybeM #-}
228−mapMaybeM :: S.MonadAsync m => Stream m Int -> m ()
256+mapMaybeM :: S.MonadAsync m => Int -> Stream m Int -> m ()
229257
230258{-# INLINE mapM #-}
231259mapM :: (S.IsStream t, S.MonadAsync m)
232− => (t m Int -> S.SerialT m Int) -> t m Int -> m ()
260+ => (t m Int -> S.SerialT m Int) -> Int -> t m Int -> m ()
233261
234262{-# INLINE sequence #-}
235263sequence :: (S.IsStream t, S.MonadAsync m)
236264 => (t m Int -> S.SerialT m Int) -> t m (m Int) -> m ()
237265
238−scan = transform . S.scanl' (+) 0
239−fmap = transform . Prelude.fmap (+1)
240−map = transform . S.map (+1)
241−mapM t = transform . t . S.mapM return
242−mapMaybe = transform . S.mapMaybe
243− (\x -> if Prelude.odd x then Nothing else Just ())
244−mapMaybeM = transform . S.mapMaybeM
245− (\x -> if Prelude.odd x then return Nothing else return $ Just ())
266+scan n = composeN n $ S.scanl' (+) 0
267+fmap n = composeN n $ Prelude.fmap (+1)
268+map n = composeN n $ S.map (+1)
269+mapM t n = composeN' n $ t . S.mapM return
270+mapMaybe n = composeN n $ S.mapMaybe
271+ (\x -> if Prelude.odd x then Nothing else Just x)
272+mapMaybeM n = composeN n $ S.mapMaybeM
273+ (\x -> if Prelude.odd x then return Nothing else return $ Just x)
246274sequence t = transform . t . S.sequence
247−filterEven = transform . S.filter even
248−filterAllOut = transform . S.filter (> maxValue)
249−filterAllIn = transform . S.filter (<= maxValue)
250−takeOne = transform . S.take 1
251−takeAll = transform . S.take maxValue
252−takeWhileTrue = transform . S.takeWhile (<= maxValue)
253−takeWhileMTrue = transform . S.takeWhileM (return . (<= maxValue))
254−dropAll = transform . S.drop maxValue
255−dropWhileTrue = transform . S.dropWhile (<= maxValue)
256−dropWhileMTrue = transform . S.dropWhileM (return . (<= maxValue))
257−findIndices = transform . S.findIndices (== maxValue)
258−elemIndices = transform . S.elemIndices maxValue
275+filterEven n = composeN n $ S.filter even
276+filterAllOut n = composeN n $ S.filter (> maxValue)
277+filterAllIn n = composeN n $ S.filter (<= maxValue)
278+takeOne n = composeN n $ S.take 1
279+takeAll n = composeN n $ S.take maxValue
280+takeWhileTrue n = composeN n $ S.takeWhile (<= maxValue)
281+takeWhileMTrue n = composeN n $ S.takeWhileM (return . (<= maxValue))
282+dropAll n = composeN n $ S.drop maxValue
283+dropWhileTrue n = composeN n $ S.dropWhile (<= maxValue)
284+dropWhileMTrue n = composeN n $ S.dropWhileM (return . (<= maxValue))
285+findIndices n = composeN n $ S.findIndices (== maxValue)
286+elemIndices n = composeN n $ S.elemIndices maxValue
259287
260288-------------------------------------------------------------------------------
261289-- Zipping and concat
@@ -289,36 +317,30 @@ zipAsyncM src = do
289317concat _n = return ()
290318
291319-------------------------------------------------------------------------------
292−-- Composition
320+-- Mixed Composition
293321-------------------------------------------------------------------------------
294322
295−{-# INLINE compose #-}
296−compose :: Monad m => (Stream m Int -> Stream m Int) -> Stream m Int -> m ()
297−compose f = transform . f . f . f . f
298−
299−{-# INLINE composeMapM #-}
300−{-# INLINE composeAllInFilters #-}
301−{-# INLINE composeAllOutFilters #-}
302−{-# INLINE composeMapAllInFilter #-}
303−composeAllInFilters, composeAllOutFilters,
304− composeMapAllInFilter
305− :: Monad m
306− => Stream m Int -> m ()
307−composeMapM :: S.MonadAsync m => Stream m Int -> m ()
308−
309−composeMapM = compose (S.mapM return)
310−composeAllInFilters = compose (S.filter (<= maxValue))
311−composeAllOutFilters = compose (S.filter (> maxValue))
312−composeMapAllInFilter =
313− compose (S.filter (<= maxValue) . Prelude.fmap (subtract 1))
314−
315−{-# INLINABLE composeScaling #-}
316−composeScaling :: Monad m => Int -> Stream m Int -> m ()
317−composeScaling 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)
323+{-# INLINE scanMap #-}
324+{-# INLINE dropMap #-}
325+{-# INLINE dropScan #-}
326+{-# INLINE takeDrop #-}
327+{-# INLINE takeScan #-}
328+{-# INLINE takeMap #-}
329+{-# INLINE filterDrop #-}
330+{-# INLINE filterTake #-}
331+{-# INLINE filterScan #-}
332+{-# INLINE filterMap #-}
333+scanMap, dropMap, dropScan, takeDrop, takeScan, takeMap, filterDrop,
334+ filterTake, filterScan, filterMap
335+ :: Monad m => Int -> Stream m Int -> m ()
336+
337+scanMap n = composeN n $ S.map (subtract 1) . S.scanl' (+) 0
338+dropMap n = composeN n $ S.map (subtract 1) . S.drop 1
339+dropScan n = composeN n $ S.scanl' (+) 0 . S.drop 1
340+takeDrop n = composeN n $ S.drop 1 . S.take maxValue
341+takeScan n = composeN n $ S.scanl' (+) 0 . S.take maxValue
342+takeMap n = composeN n $ S.map (subtract 1) . S.take maxValue
343+filterDrop n = composeN n $ S.drop 1 . S.filter (<= maxValue)
344+filterTake n = composeN n $ S.take maxValue . S.filter (<= maxValue)
345+filterScan n = composeN n $ S.scanl' (+) 0 . S.filter (<= maxBound)
346+filterMap n = composeN n $ S.map (subtract 1) . S.filter (<= maxValue)