on master help sign in
Add mixed ops x 2 and iterated benchmarks to base
bf4e5d8Harendra Kumar
benchmark/BaseStreams.hs+85−8
@@ -19,11 +19,20 @@ import qualified StreamKOps as K
19-- completely optimized out by the compiler in some cases.
19-- completely optimized out by the compiler in some cases.
20{-# INLINE benchIO #-}
20{-# INLINE benchIO #-}
21benchIO :: String -> (a IO Int -> IO ()) -> (Int -> a IO Int) -> Benchmark
21benchIO :: String -> (a IO Int -> IO ()) -> (Int -> a IO Int) -> Benchmark
22−benchIO name run f = bench name $ nfIO $ randomRIO (1,1000) >>= run . f
22+benchIO name run f = bench name $ nfIO $ randomRIO (1,1) >>= run . f
23
23
24benchFold :: NFData b
24benchFold :: NFData b
25 => String -> (t IO Int -> IO b) -> (Int -> t IO Int) -> Benchmark
25 => String -> (t IO Int -> IO b) -> (Int -> t IO Int) -> Benchmark
26−benchFold name f src = bench name $ nfIO $ randomRIO (1,1000) >>= f . src
26+benchFold name f src = bench name $ nfIO $ randomRIO (1,1) >>= f . src
27+
28+-- | Takes a source, and uses it with a default drain/fold method.
29+{-# INLINE benchD #-}
30+benchD :: String -> (Int -> D.Stream IO Int) -> Benchmark
31+benchD name f = bench name $ nfIO $ randomRIO (1,1) >>= D.toNull . f
32+
33+{-# INLINE benchK #-}
34+benchK :: String -> (Int -> K.Stream IO Int) -> Benchmark
35+benchK name f = bench name $ nfIO $ randomRIO (1,1) >>= K.toNull . f
27
36
28{-
37{-
29_benchId :: NFData b => String -> (Ops.Stream m Int -> Identity b) -> Benchmark
38_benchId :: NFData b => String -> (Ops.Stream m Int -> Identity b) -> Benchmark
@@ -60,7 +69,7 @@ main =
60 , benchIO "mapMaybe" (D.mapMaybe 1) D.sourceUnfoldrM
69 , benchIO "mapMaybe" (D.mapMaybe 1) D.sourceUnfoldrM
61 , benchIO "mapMaybeM" (D.mapMaybeM 1) D.sourceUnfoldrM
70 , benchIO "mapMaybeM" (D.mapMaybeM 1) D.sourceUnfoldrM
62 ]
71 ]
63− , bgroup "transformationN"
72+ , bgroup "transformationX4"
64 [ benchIO "scan" (D.scan 4) D.sourceUnfoldrM
73 [ benchIO "scan" (D.scan 4) D.sourceUnfoldrM
65 , benchIO "map" (D.map 4) D.sourceUnfoldrM
74 , benchIO "map" (D.map 4) D.sourceUnfoldrM
66 , benchIO "fmap" (D.fmap 4) D.sourceUnfoldrM
75 , benchIO "fmap" (D.fmap 4) D.sourceUnfoldrM
@@ -79,7 +88,7 @@ main =
79 , benchIO "dropWhile-true" (D.dropWhileTrue 1) D.sourceUnfoldrM
88 , benchIO "dropWhile-true" (D.dropWhileTrue 1) D.sourceUnfoldrM
80 , benchIO "dropWhile-false" (D.dropWhileFalse 1) D.sourceUnfoldrM
89 , benchIO "dropWhile-false" (D.dropWhileFalse 1) D.sourceUnfoldrM
81 ]
90 ]
82− , bgroup "filteringN"
91+ , bgroup "filteringX4"
83 [ benchIO "filter-even" (D.filterEven 4) D.sourceUnfoldrM
92 [ benchIO "filter-even" (D.filterEven 4) D.sourceUnfoldrM
84 , benchIO "filter-all-out" (D.filterAllOut 4) D.sourceUnfoldrM
93 , benchIO "filter-all-out" (D.filterAllOut 4) D.sourceUnfoldrM
85 , benchIO "filter-all-in" (D.filterAllIn 4) D.sourceUnfoldrM
94 , benchIO "filter-all-in" (D.filterAllIn 4) D.sourceUnfoldrM
@@ -91,7 +100,31 @@ main =
91 , benchIO "dropWhile-false" (D.dropWhileFalse 4) D.sourceUnfoldrM
100 , benchIO "dropWhile-false" (D.dropWhileFalse 4) D.sourceUnfoldrM
92 ]
101 ]
93 , benchIO "zip" D.zip D.sourceUnfoldrM
102 , benchIO "zip" D.zip D.sourceUnfoldrM
94− , bgroup "composed"
103+ , bgroup "mixed"
104+ [ benchIO "scan-map" (D.scanMap 1) D.sourceUnfoldrM
105+ , benchIO "drop-map" (D.dropMap 1) D.sourceUnfoldrM
106+ , benchIO "drop-scan" (D.dropScan 1) D.sourceUnfoldrM
107+ , benchIO "take-drop" (D.takeDrop 1) D.sourceUnfoldrM
108+ , benchIO "take-scan" (D.takeScan 1) D.sourceUnfoldrM
109+ , benchIO "take-map" (D.takeMap 1) D.sourceUnfoldrM
110+ , benchIO "filter-drop" (D.filterDrop 1) D.sourceUnfoldrM
111+ , benchIO "filter-take" (D.filterTake 1) D.sourceUnfoldrM
112+ , benchIO "filter-scan" (D.filterScan 1) D.sourceUnfoldrM
113+ , benchIO "filter-map" (D.filterMap 1) D.sourceUnfoldrM
114+ ]
115+ , bgroup "mixedX2"
116+ [ benchIO "scan-map" (D.scanMap 2) D.sourceUnfoldrM
117+ , benchIO "drop-map" (D.dropMap 2) D.sourceUnfoldrM
118+ , benchIO "drop-scan" (D.dropScan 2) D.sourceUnfoldrM
119+ , benchIO "take-drop" (D.takeDrop 2) D.sourceUnfoldrM
120+ , benchIO "take-scan" (D.takeScan 2) D.sourceUnfoldrM
121+ , benchIO "take-map" (D.takeMap 2) D.sourceUnfoldrM
122+ , benchIO "filter-drop" (D.filterDrop 2) D.sourceUnfoldrM
123+ , benchIO "filter-take" (D.filterTake 2) D.sourceUnfoldrM
124+ , benchIO "filter-scan" (D.filterScan 2) D.sourceUnfoldrM
125+ , benchIO "filter-map" (D.filterMap 2) D.sourceUnfoldrM
126+ ]
127+ , bgroup "mixedX4"
95 [ benchIO "scan-map" (D.scanMap 4) D.sourceUnfoldrM
128 [ benchIO "scan-map" (D.scanMap 4) D.sourceUnfoldrM
96 , benchIO "drop-map" (D.dropMap 4) D.sourceUnfoldrM
129 , benchIO "drop-map" (D.dropMap 4) D.sourceUnfoldrM
97 , benchIO "drop-scan" (D.dropScan 4) D.sourceUnfoldrM
130 , benchIO "drop-scan" (D.dropScan 4) D.sourceUnfoldrM
@@ -103,6 +136,15 @@ main =
103 , benchIO "filter-scan" (D.filterScan 4) D.sourceUnfoldrM
136 , benchIO "filter-scan" (D.filterScan 4) D.sourceUnfoldrM
104 , benchIO "filter-map" (D.filterMap 4) D.sourceUnfoldrM
137 , benchIO "filter-map" (D.filterMap 4) D.sourceUnfoldrM
105 ]
138 ]
139+ , bgroup "iterated"
140+ [ benchD "mapM" D.iterateMapM
141+ , benchD "scan(1/10)" D.iterateScan
142+ , benchD "filterEven" D.iterateFilterEven
143+ , benchD "takeAll" D.iterateTakeAll
144+ , benchD "dropOne" D.iterateDropOne
145+ , benchD "dropWhileFalse(1/10)" D.iterateDropWhileFalse
146+ , benchD "dropWhileTrue" D.iterateDropWhileTrue
147+ ]
106 ]
148 ]
107 , bgroup "streamK"
149 , bgroup "streamK"
108 [ bgroup "generation"
150 [ bgroup "generation"
@@ -131,12 +173,14 @@ main =
131 , bgroup "transformation"
173 , bgroup "transformation"
132 [ benchIO "scan" (K.scan 1) K.sourceUnfoldrM
174 [ benchIO "scan" (K.scan 1) K.sourceUnfoldrM
133 , benchIO "map" (K.map 1) K.sourceUnfoldrM
175 , benchIO "map" (K.map 1) K.sourceUnfoldrM
176+ , benchIO "fmap" (K.fmap 1) K.sourceUnfoldrM
134 , benchIO "mapM" (K.mapM 1) K.sourceUnfoldrM
177 , benchIO "mapM" (K.mapM 1) K.sourceUnfoldrM
135 -- , benchIO "concat" K.concat K.sourceUnfoldrM
178 -- , benchIO "concat" K.concat K.sourceUnfoldrM
136 ]
179 ]
137− , bgroup "transformationN"
180+ , bgroup "transformationX4"
138 [ benchIO "scan" (K.scan 4) K.sourceUnfoldrM
181 [ benchIO "scan" (K.scan 4) K.sourceUnfoldrM
139 , benchIO "map" (K.map 4) K.sourceUnfoldrM
182 , benchIO "map" (K.map 4) K.sourceUnfoldrM
183+ , benchIO "fmap" (K.fmap 4) K.sourceUnfoldrM
140 , benchIO "mapM" (K.mapM 4) K.sourceUnfoldrM
184 , benchIO "mapM" (K.mapM 4) K.sourceUnfoldrM
141 -- , benchIO "concat" K.concat K.sourceUnfoldrM
185 -- , benchIO "concat" K.concat K.sourceUnfoldrM
142 ]
186 ]
@@ -151,7 +195,7 @@ main =
151 , benchIO "dropWhile-true" (K.dropWhileTrue 1) K.sourceUnfoldrM
195 , benchIO "dropWhile-true" (K.dropWhileTrue 1) K.sourceUnfoldrM
152 , benchIO "dropWhile-false" (K.dropWhileFalse 1) K.sourceUnfoldrM
196 , benchIO "dropWhile-false" (K.dropWhileFalse 1) K.sourceUnfoldrM
153 ]
197 ]
154− , bgroup "filteringN"
198+ , bgroup "filteringX4"
155 [ benchIO "filter-even" (K.filterEven 4) K.sourceUnfoldrM
199 [ benchIO "filter-even" (K.filterEven 4) K.sourceUnfoldrM
156 , benchIO "filter-all-out" (K.filterAllOut 4) K.sourceUnfoldrM
200 , benchIO "filter-all-out" (K.filterAllOut 4) K.sourceUnfoldrM
157 , benchIO "filter-all-in" (K.filterAllIn 4) K.sourceUnfoldrM
201 , benchIO "filter-all-in" (K.filterAllIn 4) K.sourceUnfoldrM
@@ -163,7 +207,31 @@ main =
163 , benchIO "dropWhile-false" (K.dropWhileFalse 4) K.sourceUnfoldrM
207 , benchIO "dropWhile-false" (K.dropWhileFalse 4) K.sourceUnfoldrM
164 ]
208 ]
165 , benchIO "zip" K.zip K.sourceUnfoldrM
209 , benchIO "zip" K.zip K.sourceUnfoldrM
166− , bgroup "composed"
210+ , bgroup "mixed"
211+ [ benchIO "scan-map" (K.scanMap 1) K.sourceUnfoldrM
212+ , benchIO "drop-map" (K.dropMap 1) K.sourceUnfoldrM
213+ , benchIO "drop-scan" (K.dropScan 1) K.sourceUnfoldrM
214+ , benchIO "take-drop" (K.takeDrop 1) K.sourceUnfoldrM
215+ , benchIO "take-scan" (K.takeScan 1) K.sourceUnfoldrM
216+ , benchIO "take-map" (K.takeMap 1) K.sourceUnfoldrM
217+ , benchIO "filter-drop" (K.filterDrop 1) K.sourceUnfoldrM
218+ , benchIO "filter-take" (K.filterTake 1) K.sourceUnfoldrM
219+ , benchIO "filter-scan" (K.filterScan 1) K.sourceUnfoldrM
220+ , benchIO "filter-map" (K.filterMap 1) K.sourceUnfoldrM
221+ ]
222+ , bgroup "mixedX2"
223+ [ benchIO "scan-map" (K.scanMap 2) K.sourceUnfoldrM
224+ , benchIO "drop-map" (K.dropMap 2) K.sourceUnfoldrM
225+ , benchIO "drop-scan" (K.dropScan 2) K.sourceUnfoldrM
226+ , benchIO "take-drop" (K.takeDrop 2) K.sourceUnfoldrM
227+ , benchIO "take-scan" (K.takeScan 2) K.sourceUnfoldrM
228+ , benchIO "take-map" (K.takeMap 2) K.sourceUnfoldrM
229+ , benchIO "filter-drop" (K.filterDrop 2) K.sourceUnfoldrM
230+ , benchIO "filter-take" (K.filterTake 2) K.sourceUnfoldrM
231+ , benchIO "filter-scan" (K.filterScan 2) K.sourceUnfoldrM
232+ , benchIO "filter-map" (K.filterMap 2) K.sourceUnfoldrM
233+ ]
234+ , bgroup "mixedX4"
167 [ benchIO "scan-map" (K.scanMap 4) K.sourceUnfoldrM
235 [ benchIO "scan-map" (K.scanMap 4) K.sourceUnfoldrM
168 , benchIO "drop-map" (K.dropMap 4) K.sourceUnfoldrM
236 , benchIO "drop-map" (K.dropMap 4) K.sourceUnfoldrM
169 , benchIO "drop-scan" (K.dropScan 4) K.sourceUnfoldrM
237 , benchIO "drop-scan" (K.dropScan 4) K.sourceUnfoldrM
@@ -175,5 +243,14 @@ main =
175 , benchIO "filter-scan" (K.filterScan 4) K.sourceUnfoldrM
243 , benchIO "filter-scan" (K.filterScan 4) K.sourceUnfoldrM
176 , benchIO "filter-map" (K.filterMap 4) K.sourceUnfoldrM
244 , benchIO "filter-map" (K.filterMap 4) K.sourceUnfoldrM
177 ]
245 ]
246+ , bgroup "iterated"
247+ [ benchK "mapM" K.iterateMapM
248+ , benchK "scan(1/10)" K.iterateScan
249+ , benchK "filterEven" K.iterateFilterEven
250+ , benchK "takeAll" K.iterateTakeAll
251+ , benchK "dropOne" K.iterateDropOne
252+ , benchK "dropWhileFalse(1/10)" K.iterateDropWhileFalse
253+ , benchK "dropWhileTrue" K.iterateDropWhileTrue
254+ ]
178 ]
255 ]
179 ]
256 ]
benchmark/Chart.hs+83−32
@@ -7,8 +7,10 @@ module Main where
7import Control.Exception (handle, catch, SomeException, ErrorCall(..))
7import Control.Exception (handle, catch, SomeException, ErrorCall(..))
8import Control.Monad.Trans.State
8import Control.Monad.Trans.State
9import Control.Monad.Trans.Maybe
9import Control.Monad.Trans.Maybe
10+import Data.Function (on, (&))
10import Data.List
11import Data.List
11import Data.List.Split
12import Data.List.Split
13+import Data.Maybe (mapMaybe)
12import Data.Ord (comparing)
14import Data.Ord (comparing)
13import System.Environment (getArgs)
15import System.Environment (getArgs)
14import Control.Monad.IO.Class (liftIO)
16import Control.Monad.IO.Class (liftIO)
@@ -100,21 +102,21 @@ ignoringErr a = catch a (\(ErrorCall err :: ErrorCall) ->
100------------------------------------------------------------------------------
102------------------------------------------------------------------------------
101
103
102makeLinearGraphs :: Config -> String -> IO ()
104makeLinearGraphs :: Config -> String -> IO ()
103−makeLinearGraphs cfg inputFile = do
105+makeLinearGraphs cfg@Config{..} inputFile = do
104 ignoringErr $ graph inputFile "generation" $ cfg
106 ignoringErr $ graph inputFile "generation" $ cfg
105− { title = Just "Generation"
107+ { title = (++) <$> title <*> Just " generation"
106 , classifyBenchmark =
108 , classifyBenchmark =
107 fmap ("Streamly",) . stripPrefix "serially/generation/"
109 fmap ("Streamly",) . stripPrefix "serially/generation/"
108 }
110 }
109
111
110 ignoringErr $ graph inputFile "elimination" $ cfg
112 ignoringErr $ graph inputFile "elimination" $ cfg
111− { title = Just "Elimination"
113+ { title = (++) <$> title <*> Just " Elimination"
112 , classifyBenchmark =
114 , classifyBenchmark =
113 fmap ("Streamly",) . stripPrefix "serially/elimination/"
115 fmap ("Streamly",) . stripPrefix "serially/elimination/"
114 }
116 }
115
117
116 ignoringErr $ graph inputFile "transformation-zip" $ cfg
118 ignoringErr $ graph inputFile "transformation-zip" $ cfg
117− { title = Just "Transformation & Zip"
119+ { title = (++) <$> title <*> Just " Transformation & Zip"
118 , classifyBenchmark = \b ->
120 , classifyBenchmark = \b ->
119 if "serially/transformation/" `isPrefixOf` b
121 if "serially/transformation/" `isPrefixOf` b
120 || "serially/zip" `isPrefixOf` b
122 || "serially/zip" `isPrefixOf` b
@@ -123,34 +125,34 @@ makeLinearGraphs cfg inputFile = do
123 }
125 }
124
126
125 ignoringErr $ graph inputFile "filtering" $ cfg
127 ignoringErr $ graph inputFile "filtering" $ cfg
126− { title = Just "Filtering"
128+ { title = (++) <$> title <*> Just " Filtering"
127 , classifyBenchmark =
129 , classifyBenchmark =
128 fmap ("Streamly",) . stripPrefix "serially/filtering/"
130 fmap ("Streamly",) . stripPrefix "serially/filtering/"
129 }
131 }
130
132
131 ignoringErr $ graph inputFile "transformationX4" $ cfg
133 ignoringErr $ graph inputFile "transformationX4" $ cfg
132− { title = Just "Transformation x 4"
134+ { title = (++) <$> title <*> Just " Transformation x 4"
133 , classifyBenchmark =
135 , classifyBenchmark =
134 fmap ("Streamly",) . stripPrefix "serially/transformationX4/"
136 fmap ("Streamly",) . stripPrefix "serially/transformationX4/"
135 }
137 }
136
138
137 ignoringErr $ graph inputFile "filteringX4"
139 ignoringErr $ graph inputFile "filteringX4"
138 $ cfg
140 $ cfg
139− { title = Just "Filtering x 4"
141+ { title = (++) <$> title <*> Just " Filtering x 4"
140 , classifyBenchmark =
142 , classifyBenchmark =
141 fmap ("Streamly",) . stripPrefix "serially/filteringX4/"
143 fmap ("Streamly",) . stripPrefix "serially/filteringX4/"
142 }
144 }
143
145
144 ignoringErr $ graph inputFile "mixedX4"
146 ignoringErr $ graph inputFile "mixedX4"
145 $ cfg
147 $ cfg
146− { title = Just "Mixed x 4"
148+ { title = (++) <$> title <*> Just " Mixed x 4"
147 , classifyBenchmark =
149 , classifyBenchmark =
148 fmap ("Streamly",) . stripPrefix "serially/mixedX4/"
150 fmap ("Streamly",) . stripPrefix "serially/mixedX4/"
149 }
151 }
150
152
151 ignoringErr $ graph inputFile "iterated"
153 ignoringErr $ graph inputFile "iterated"
152 $ cfg
154 $ cfg
153− { title = Just "Iterate 10 x 100000"
155+ { title = Just "iterate 10,000 times over 10 elems"
154 , classifyBenchmark =
156 , classifyBenchmark =
155 fmap ("Streamly",) . stripPrefix "serially/iterated/"
157 fmap ("Streamly",) . stripPrefix "serially/iterated/"
156 }
158 }
@@ -161,23 +163,61 @@ makeLinearGraphs cfg inputFile = do
161
163
162makeNestedGraphs :: Config -> String -> IO ()
164makeNestedGraphs :: Config -> String -> IO ()
163makeNestedGraphs cfg inputFile =
165makeNestedGraphs cfg inputFile =
164− ignoringErr $ graph inputFile "nested-serial" $ cfg
166+ ignoringErr $ graph inputFile "nested-all" $ cfg
165− { title = Just "Nested serial"
167+ { presentation = Groups Absolute
166− , classifyBenchmark = \b ->
168+ , classifyBenchmark = classifyNested
167− let ls = splitOn "/" b
169+ , selectGroups = \gs ->
168− in case head ls of
170+ groupBy ((==) `on` snd) gs
169− "serially" -> Just (head ls, last ls)
171+ & fmap (\xs -> mapMaybe (\x -> (x,) <$> lookup x xs) order)
170− _ -> Nothing
172+ & concat
171 }
173 }
172
174
175+ where
176+
177+ order = ["serially", "asyncly", "wAsyncly", "aheadly", "parallely"]
178+
179+ classifyNested b
180+ | "serially/" `isPrefixOf` b =
181+ ("serially",) <$> stripPrefix "serially/" b
182+ | "asyncly/" `isPrefixOf` b =
183+ ("asyncly",) <$> stripPrefix "asyncly/" b
184+ | "wAsyncly/" `isPrefixOf` b =
185+ ("wAsyncly",) <$> stripPrefix "wAsyncly/" b
186+ | "aheadly/" `isPrefixOf` b =
187+ ("aheadly",) <$> stripPrefix "aheadly/" b
188+ | "parallely/" `isPrefixOf` b =
189+ ("parallely",) <$> stripPrefix "parallely/" b
190+ | otherwise = Nothing
191+
173------------------------------------------------------------------------------
192------------------------------------------------------------------------------
174-- Charts for parallel streams
193-- Charts for parallel streams
175------------------------------------------------------------------------------
194------------------------------------------------------------------------------
176
195
177makeLinearAsyncGraphs :: Config -> String -> IO ()
196makeLinearAsyncGraphs :: Config -> String -> IO ()
178−makeLinearAsyncGraphs cfg inputFile = do
197+makeLinearAsyncGraphs cfg inputFile =
179− putStrLn "Not implemented"
198+ ignoringErr $ graph inputFile "linear-async" cfg
180− return ()
199+ { presentation = Groups Absolute
200+ , classifyBenchmark = classifyAsync
201+ , selectGroups = \gs ->
202+ groupBy ((==) `on` snd) gs
203+ & fmap (\xs -> mapMaybe (\x -> (x,) <$> lookup x xs) order)
204+ & concat
205+ }
206+
207+ where
208+
209+ order = ["asyncly", "wAsyncly", "aheadly", "parallely"]
210+
211+ classifyAsync b
212+ | "asyncly/" `isPrefixOf` b =
213+ ("asyncly",) <$> stripPrefix "asyncly/" b
214+ | "wAsyncly/" `isPrefixOf` b =
215+ ("wAsyncly",) <$> stripPrefix "wAsyncly/" b
216+ | "aheadly/" `isPrefixOf` b =
217+ ("aheadly",) <$> stripPrefix "aheadly/" b
218+ | "parallely/" `isPrefixOf` b =
219+ ("parallely",) <$> stripPrefix "parallely/" b
220+ | otherwise = Nothing
181
221
182makeLinearRateGraphs :: Config -> String -> IO ()
222makeLinearRateGraphs :: Config -> String -> IO ()
183makeLinearRateGraphs cfg inputFile = do
223makeLinearRateGraphs cfg inputFile = do
@@ -188,18 +228,22 @@ makeLinearRateGraphs cfg inputFile = do
188-- Reports/Charts for base streams
228-- Reports/Charts for base streams
189------------------------------------------------------------------------------
229------------------------------------------------------------------------------
190
230
191−classifyBase b
192− | "streamD/" `isPrefixOf` b = ("streamD",) <$> stripPrefix "streamD/" b
193− | "streamK/" `isPrefixOf` b = ("streamK",) <$> stripPrefix "streamK/" b
194− | otherwise = Nothing
195−
196showStreamDVsK Options{..} cfg inp out =
231showStreamDVsK Options{..} cfg inp out =
197 let cfg' = cfg { classifyBenchmark = classifyBase }
232 let cfg' = cfg { classifyBenchmark = classifyBase }
198 in if genGraphs
233 in if genGraphs
199 then ignoringErr $ graph inp "streamD-vs-streamK"
234 then ignoringErr $ graph inp "streamD-vs-streamK"
200− cfg' {outputDir = Just out}
235+ cfg' { outputDir = Just out
236+ , presentation = Groups Absolute
237+ }
201 else ignoringErr $ report inp Nothing cfg'
238 else ignoringErr $ report inp Nothing cfg'
202
239
240+ where
241+
242+ classifyBase b
243+ | "streamD/" `isPrefixOf` b = ("streamD",) <$> stripPrefix "streamD/" b
244+ | "streamK/" `isPrefixOf` b = ("streamK",) <$> stripPrefix "streamK/" b
245+ | otherwise = Nothing
246+
203showStreamD Options{..} cfg inp out =
247showStreamD Options{..} cfg inp out =
204 let cfg' = cfg { classifyBenchmark = classifyStreamD }
248 let cfg' = cfg { classifyBenchmark = classifyStreamD }
205 in if genGraphs
249 in if genGraphs
@@ -258,27 +302,34 @@ main = do
258 return ()
302 return ()
259 Just opts@Options{..} ->
303 Just opts@Options{..} ->
260 case benchType of
304 case benchType of
261− Linear -> benchShow opts cfg makeLinearGraphs
305+ Linear -> benchShow opts cfg
306+ { title = Just "100,000 elems" }
307+ makeLinearGraphs
262 "charts/linear/results.csv"
308 "charts/linear/results.csv"
263 "charts/linear"
309 "charts/linear"
264− LinearAsync -> benchShow opts cfg makeLinearAsyncGraphs
310+ LinearAsync -> benchShow opts cfg
311+ { title = Just "Async 10,000 elems" }
312+ makeLinearAsyncGraphs
265 "charts/linear-async/results.csv"
313 "charts/linear-async/results.csv"
266 "charts/linear-async"
314 "charts/linear-async"
267 LinearRate -> benchShow opts cfg makeLinearRateGraphs
315 LinearRate -> benchShow opts cfg makeLinearRateGraphs
268 "charts/linear-rate/results.csv"
316 "charts/linear-rate/results.csv"
269 "charts/linear-rate"
317 "charts/linear-rate"
270− Nested -> benchShow opts cfg makeNestedGraphs
318+ Nested -> benchShow opts cfg
319+ { title = Just "Nested loops 100 x 100 elems" }
320+ makeNestedGraphs
271 "charts/nested/results.csv"
321 "charts/nested/results.csv"
272 "charts/nested"
322 "charts/nested"
273− Base ->
323+ Base -> do
324+ let cfg' = cfg { title = Just "100,000 elems" }
274 if groupDiff
325 if groupDiff
275− then showStreamDVsK opts cfg
326+ then showStreamDVsK opts cfg'
276 "charts/base/results.csv"
327 "charts/base/results.csv"
277 "charts/base"
328 "charts/base"
278 else do
329 else do
279− showStreamD opts cfg
330+ showStreamD opts cfg'
280 "charts/base/results.csv"
331 "charts/base/results.csv"
281 "charts/base"
332 "charts/base"
282− showStreamK opts cfg
333+ showStreamK opts cfg'
283 "charts/base/results.csv"
334 "charts/base/results.csv"
284 "charts/base"
335 "charts/base"
benchmark/Linear.hs+3−3
@@ -96,7 +96,7 @@ main =
96 , benchIO "elemIndices" (Ops.elemIndices 1)
96 , benchIO "elemIndices" (Ops.elemIndices 1)
97 -- , benchIO "concat" Ops.concat
97 -- , benchIO "concat" Ops.concat
98 ]
98 ]
99− , bgroup "transformationN"
99+ , bgroup "transformationX4"
100 [ benchIO "scan" (Ops.scan 4)
100 [ benchIO "scan" (Ops.scan 4)
101 , benchIO "map" (Ops.map 4)
101 , benchIO "map" (Ops.map 4)
102 , benchIO "fmap" (Ops.fmap 4)
102 , benchIO "fmap" (Ops.fmap 4)
@@ -122,7 +122,7 @@ main =
122 --, benchIO "dropWhileM-true" (Ops.dropWhileMTrue 1)
122 --, benchIO "dropWhileM-true" (Ops.dropWhileMTrue 1)
123 , benchIO "dropWhile-false" (Ops.dropWhileFalse 1)
123 , benchIO "dropWhile-false" (Ops.dropWhileFalse 1)
124 ]
124 ]
125− , bgroup "filteringN"
125+ , bgroup "filteringX4"
126 [ benchIO "filter-even" (Ops.filterEven 4)
126 [ benchIO "filter-even" (Ops.filterEven 4)
127 , benchIO "filter-all-out" (Ops.filterAllOut 4)
127 , benchIO "filter-all-out" (Ops.filterAllOut 4)
128 , benchIO "filter-all-in" (Ops.filterAllIn 4)
128 , benchIO "filter-all-in" (Ops.filterAllIn 4)
@@ -137,7 +137,7 @@ main =
137 ]
137 ]
138 , benchIO "zip" Ops.zip
138 , benchIO "zip" Ops.zip
139 , benchIO "zipM" Ops.zipM
139 , benchIO "zipM" Ops.zipM
140− , bgroup "composed"
140+ , bgroup "mixedX4"
141 [ benchIO "scan-map" (Ops.scanMap 4)
141 [ benchIO "scan-map" (Ops.scanMap 4)
142 , benchIO "drop-map" (Ops.dropMap 4)
142 , benchIO "drop-map" (Ops.dropMap 4)
143 , benchIO "drop-scan" (Ops.dropScan 4)
143 , benchIO "drop-scan" (Ops.dropScan 4)
benchmark/LinearOps.hs+15−11
@@ -16,7 +16,7 @@ import Data.Maybe (fromJust)
16import Prelude
16import Prelude
17 (Monad, Int, (+), ($), (.), return, fmap, even, (>), (<=), (==), (<=),
17 (Monad, Int, (+), ($), (.), return, fmap, even, (>), (<=), (==), (<=),
18 subtract, undefined, Maybe(..), odd, Bool, not, (>>=), mapM_, curry,
18 subtract, undefined, Maybe(..), odd, Bool, not, (>>=), mapM_, curry,
19− maxBound)
19+ maxBound, div)
20import qualified Prelude as P
20import qualified Prelude as P
21
21
22import qualified Streamly as S
22import qualified Streamly as S
@@ -287,7 +287,7 @@ dropOne n = composeN n $ S.drop 1
287dropAll n = composeN n $ S.drop maxValue
287dropAll n = composeN n $ S.drop maxValue
288dropWhileTrue n = composeN n $ S.dropWhile (<= maxValue)
288dropWhileTrue n = composeN n $ S.dropWhile (<= maxValue)
289dropWhileMTrue n = composeN n $ S.dropWhileM (return . (<= maxValue))
289dropWhileMTrue n = composeN n $ S.dropWhileM (return . (<= maxValue))
290−dropWhileFalse n = composeN n $ S.dropWhile (<= 1)
290+dropWhileFalse n = composeN n $ S.dropWhile (> maxValue)
291findIndices n = composeN n $ S.findIndices (== maxValue)
291findIndices n = composeN n $ S.findIndices (== maxValue)
292elemIndices n = composeN n $ S.elemIndices maxValue
292elemIndices n = composeN n $ S.elemIndices maxValue
293
293
@@ -295,11 +295,15 @@ elemIndices n = composeN n $ S.elemIndices maxValue
295-- Iteration
295-- Iteration
296-------------------------------------------------------------------------------
296-------------------------------------------------------------------------------
297
297
298+iterStreamLen, maxIters :: Int
299+iterStreamLen = 10
300+maxIters = 10000
301+
298{-# INLINE iterateSource #-}
302{-# INLINE iterateSource #-}
299iterateSource
303iterateSource
300 :: S.MonadAsync m
304 :: S.MonadAsync m
301 => (Stream m Int -> Stream m Int) -> Int -> Int -> Stream m Int
305 => (Stream m Int -> Stream m Int) -> Int -> Int -> Stream m Int
302−iterateSource g i n = f i (sourceUnfoldrMN 10 n)
306+iterateSource g i n = f i (sourceUnfoldrMN iterStreamLen n)
303 where
307 where
304 f (0 :: Int) m = g m
308 f (0 :: Int) m = g m
305 f x m = g (f (x P.- 1) m)
309 f x m = g (f (x P.- 1) m)
@@ -317,14 +321,14 @@ iterateMapM, iterateScan, iterateFilterEven, iterateTakeAll, iterateDropOne,
317 => Int -> Stream m Int
321 => Int -> Stream m Int
318
322
319-- this is quadratic
323-- this is quadratic
320−iterateScan = iterateSource (S.scanl' (+) 0) 1000
324+iterateScan = iterateSource (S.scanl' (+) 0) (maxIters `div` 10)
321−
325+
322−iterateMapM = iterateSource (S.mapM return) 100000
326+iterateMapM = iterateSource (S.mapM return) maxIters
323−iterateFilterEven = iterateSource (S.filter even) 100000
327+iterateFilterEven = iterateSource (S.filter even) maxIters
324−iterateTakeAll = iterateSource (S.take maxValue) 100000
328+iterateTakeAll = iterateSource (S.take maxValue) maxIters
325−iterateDropOne = iterateSource (S.drop 1) 100000
329+iterateDropOne = iterateSource (S.drop 1) maxIters
326−iterateDropWhileFalse = iterateSource (S.dropWhile (<= 1)) 100000
330+iterateDropWhileFalse = iterateSource (S.dropWhile (> maxValue)) maxIters
327−iterateDropWhileTrue = iterateSource (S.dropWhile (<= maxValue)) 100000
331+iterateDropWhileTrue = iterateSource (S.dropWhile (<= maxValue)) maxIters
328
332
329-------------------------------------------------------------------------------
333-------------------------------------------------------------------------------
330-- Zipping and concat
334-- Zipping and concat
benchmark/StreamDOps.hs+54−2
@@ -6,15 +6,17 @@
6-- Maintainer : harendra.kumar@gmail.com
6-- Maintainer : harendra.kumar@gmail.com
7
7
8{-# LANGUAGE FlexibleContexts #-}
8{-# LANGUAGE FlexibleContexts #-}
9+{-# LANGUAGE ScopedTypeVariables #-}
9
10
10module StreamDOps where
11module StreamDOps where
11
12
12import Control.Monad (when)
13import Control.Monad (when)
13import Data.Maybe (isJust)
14import Data.Maybe (isJust)
14import Prelude
15import Prelude
15− (Monad, Int, (+), ($), (.), return, (>), even, (<=),
16+ (Monad, Int, (+), ($), (.), return, (>), even, (<=), div,
16 subtract, undefined, Maybe(..), not, mapM_, (>>=),
17 subtract, undefined, Maybe(..), not, mapM_, (>>=),
17 maxBound, fmap, odd)
18 maxBound, fmap, odd)
19+import qualified Prelude as P
18
20
19import qualified Streamly.Streams.StreamD as S
21import qualified Streamly.Streams.StreamD as S
20
22
@@ -63,6 +65,15 @@ sourceUnfoldr n = S.unfoldr step n
63 then Nothing
65 then Nothing
64 else Just (cnt, cnt + 1)
66 else Just (cnt, cnt + 1)
65
67
68+{-# INLINE sourceUnfoldrMN #-}
69+sourceUnfoldrMN :: Monad m => Int -> Int -> Stream m Int
70+sourceUnfoldrMN 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))
76+
66{-# INLINE sourceUnfoldrM #-}
77{-# INLINE sourceUnfoldrM #-}
67sourceUnfoldrM :: Monad m => Int -> Stream m Int
78sourceUnfoldrM :: Monad m => Int -> Stream m Int
68sourceUnfoldrM n = S.unfoldrM step n
79sourceUnfoldrM n = S.unfoldrM step n
@@ -141,6 +152,7 @@ composeN n f =
141{-# INLINE fmap #-}
152{-# INLINE fmap #-}
142{-# INLINE mapM #-}
153{-# INLINE mapM #-}
143{-# INLINE mapMaybe #-}
154{-# INLINE mapMaybe #-}
155+{-# INLINE mapMaybeM #-}
144{-# INLINE filterEven #-}
156{-# INLINE filterEven #-}
145{-# INLINE filterAllOut #-}
157{-# INLINE filterAllOut #-}
146{-# INLINE filterAllIn #-}
158{-# INLINE filterAllIn #-}
@@ -178,7 +190,47 @@ dropOne n = composeN n $ S.drop 1
178dropAll n = composeN n $ S.drop maxValue
190dropAll n = composeN n $ S.drop maxValue
179dropWhileTrue n = composeN n $ S.dropWhile (<= maxValue)
191dropWhileTrue n = composeN n $ S.dropWhile (<= maxValue)
180dropWhileMTrue n = composeN n $ S.dropWhileM (return . (<= maxValue))
192dropWhileMTrue n = composeN n $ S.dropWhileM (return . (<= maxValue))
181−dropWhileFalse n = composeN n $ S.dropWhile (<= 1)
193+dropWhileFalse n = composeN n $ S.dropWhile (> maxValue)
194+
195+-------------------------------------------------------------------------------
196+-- Iteration
197+-------------------------------------------------------------------------------
198+
199+iterStreamLen, maxIters :: Int
200+iterStreamLen = 10
201+maxIters = 10000
202+
203+{-# INLINE iterateSource #-}
204+iterateSource
205+ :: Monad m
206+ => (Stream m Int -> Stream m Int) -> Int -> Int -> Stream m Int
207+iterateSource 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)
211+
212+{-# INLINE iterateMapM #-}
213+{-# INLINE iterateScan #-}
214+{-# INLINE iterateFilterEven #-}
215+{-# INLINE iterateTakeAll #-}
216+{-# INLINE iterateDropOne #-}
217+{-# INLINE iterateDropWhileFalse #-}
218+{-# INLINE iterateDropWhileTrue #-}
219+iterateMapM, iterateScan, iterateFilterEven, iterateTakeAll, iterateDropOne,
220+ iterateDropWhileFalse, iterateDropWhileTrue
221+ :: Monad m
222+ => Int -> Stream m Int
223+
224+-- this is quadratic
225+iterateScan = iterateSource (S.scanl' (+) 0) (maxIters `div` 10)
226+iterateDropWhileFalse = iterateSource (S.dropWhile (> maxValue))
227+ (maxIters `div` 10)
228+
229+iterateMapM = iterateSource (S.mapM return) maxIters
230+iterateFilterEven = iterateSource (S.filter even) maxIters
231+iterateTakeAll = iterateSource (S.take maxValue) maxIters
232+iterateDropOne = iterateSource (S.drop 1) maxIters
233+iterateDropWhileTrue = iterateSource (S.dropWhile (<= maxValue)) maxIters
182
234
183-------------------------------------------------------------------------------
235-------------------------------------------------------------------------------
184-- Zipping and concat
236-- Zipping and concat
benchmark/StreamKOps.hs+56−3
@@ -6,15 +6,17 @@
6-- Maintainer : harendra.kumar@gmail.com
6-- Maintainer : harendra.kumar@gmail.com
7
7
8{-# LANGUAGE FlexibleContexts #-}
8{-# LANGUAGE FlexibleContexts #-}
9+{-# LANGUAGE ScopedTypeVariables #-}
9
10
10module StreamKOps where
11module StreamKOps where
11
12
12import Control.Monad (when)
13import Control.Monad (when)
13import Data.Maybe (isJust)
14import Data.Maybe (isJust)
14import Prelude
15import Prelude
15− (Monad, Int, (+), ($), (.), return, fmap, even, (>), (<=),
16+ (Monad, Int, (+), ($), (.), return, even, (>), (<=), div,
16 subtract, undefined, Maybe(..), not, mapM_, (>>=),
17 subtract, undefined, Maybe(..), not, mapM_, (>>=),
17 maxBound)
18 maxBound)
19+import qualified Prelude as P
18
20
19import qualified Streamly.Streams.StreamK as S
21import qualified Streamly.Streams.StreamK as S
20import qualified Streamly.Streams.Prelude as S
22import qualified Streamly.Streams.Prelude as S
@@ -69,6 +71,15 @@ sourceUnfoldrM n = S.unfoldrM step n
69 then return Nothing
71 then return Nothing
70 else return (Just (cnt, cnt + 1))
72 else return (Just (cnt, cnt + 1))
71
73
74+{-# INLINE sourceUnfoldrMN #-}
75+sourceUnfoldrMN :: S.MonadAsync m => Int -> Int -> Stream m Int
76+sourceUnfoldrMN 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))
82+
72{-
83{-
73{-# INLINE sourceFromEnum #-}
84{-# INLINE sourceFromEnum #-}
74sourceFromEnum :: Monad m => Int -> Stream m Int
85sourceFromEnum :: Monad m => Int -> Stream m Int
@@ -156,6 +167,7 @@ composeN n f =
156
167
157{-# INLINE scan #-}
168{-# INLINE scan #-}
158{-# INLINE map #-}
169{-# INLINE map #-}
170+{-# INLINE fmap #-}
159{-# INLINE filterEven #-}
171{-# INLINE filterEven #-}
160{-# INLINE filterAllOut #-}
172{-# INLINE filterAllOut #-}
161{-# INLINE filterAllIn #-}
173{-# INLINE filterAllIn #-}
@@ -166,7 +178,7 @@ composeN n f =
166{-# INLINE dropAll #-}
178{-# INLINE dropAll #-}
167{-# INLINE dropWhileTrue #-}
179{-# INLINE dropWhileTrue #-}
168{-# INLINE dropWhileFalse #-}
180{-# INLINE dropWhileFalse #-}
169−scan, map, filterEven, filterAllOut,
181+scan, map, fmap, filterEven, filterAllOut,
170 filterAllIn, takeOne, takeAll, takeWhileTrue, dropAll, dropOne,
182 filterAllIn, takeOne, takeAll, takeWhileTrue, dropAll, dropOne,
171 dropWhileTrue, dropWhileFalse
183 dropWhileTrue, dropWhileFalse
172 :: Monad m
184 :: Monad m
@@ -176,7 +188,8 @@ scan, map, filterEven, filterAllOut,
176mapM :: S.MonadAsync m => Int -> Stream m Int -> m ()
188mapM :: S.MonadAsync m => Int -> Stream m Int -> m ()
177
189
178scan n = composeN n $ S.scanl' (+) 0
190scan n = composeN n $ S.scanl' (+) 0
179−map n = composeN n $ fmap (+1)
191+map n = composeN n $ P.fmap (+1)
192+fmap n = composeN n $ P.fmap (+1)
180mapM n = composeN n $ S.mapM return
193mapM n = composeN n $ S.mapM return
181filterEven n = composeN n $ S.filter even
194filterEven n = composeN n $ S.filter even
182filterAllOut n = composeN n $ S.filter (> maxValue)
195filterAllOut n = composeN n $ S.filter (> maxValue)
@@ -189,6 +202,46 @@ dropAll n = composeN n $ S.drop maxValue
189dropWhileTrue n = composeN n $ S.dropWhile (<= maxValue)
202dropWhileTrue n = composeN n $ S.dropWhile (<= maxValue)
190dropWhileFalse n = composeN n $ S.dropWhile (<= 1)
203dropWhileFalse n = composeN n $ S.dropWhile (<= 1)
191
204
205+-------------------------------------------------------------------------------
206+-- Iteration
207+-------------------------------------------------------------------------------
208+
209+iterStreamLen, maxIters :: Int
210+iterStreamLen = 10
211+maxIters = 10000
212+
213+{-# INLINE iterateSource #-}
214+iterateSource
215+ :: S.MonadAsync m
216+ => (Stream m Int -> Stream m Int) -> Int -> Int -> Stream m Int
217+iterateSource 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)
221+
222+{-# INLINE iterateMapM #-}
223+{-# INLINE iterateScan #-}
224+{-# INLINE iterateFilterEven #-}
225+{-# INLINE iterateTakeAll #-}
226+{-# INLINE iterateDropOne #-}
227+{-# INLINE iterateDropWhileFalse #-}
228+{-# INLINE iterateDropWhileTrue #-}
229+iterateMapM, iterateScan, iterateFilterEven, iterateTakeAll, iterateDropOne,
230+ iterateDropWhileFalse, iterateDropWhileTrue
231+ :: S.MonadAsync m
232+ => Int -> Stream m Int
233+
234+-- this is quadratic
235+iterateScan = iterateSource (S.scanl' (+) 0) (maxIters `div` 10)
236+iterateDropWhileFalse = iterateSource (S.dropWhile (> maxValue))
237+ (maxIters `div` 10)
238+
239+iterateMapM = iterateSource (S.mapM return) maxIters
240+iterateFilterEven = iterateSource (S.filter even) maxIters
241+iterateTakeAll = iterateSource (S.take maxValue) maxIters
242+iterateDropOne = iterateSource (S.drop 1) maxIters
243+iterateDropWhileTrue = iterateSource (S.dropWhile (<= maxValue)) maxIters
244+
192-------------------------------------------------------------------------------
245-------------------------------------------------------------------------------
193-- Zipping and concat
246-- Zipping and concat
194-------------------------------------------------------------------------------
247-------------------------------------------------------------------------------