1{-# LANGUAGE TupleSections #-}
2{-# LANGUAGE RecordWildCards #-}
3{-# LANGUAGE ScopedTypeVariables #-}
7import Control.Exception (handle, catch, SomeException, ErrorCall(..))
8import Control.Monad.Trans.State
9import Control.Monad.Trans.Maybe
10import Data.Function (on, (&))
13import Data.Maybe (mapMaybe)
14import Data.Ord (comparing)
15import System.Environment (getArgs)
16import Control.Monad.IO.Class (liftIO)
17import Control.Monad (mzero)
21------------------------------------------------------------------------------
22-- Command line parsing
23------------------------------------------------------------------------------
25data BenchType = Linear | LinearAsync | LinearRate | Nested | Base
31 , benchType :: BenchType
34defaultOptions = Options False False Linear
38 put (args, opts { genGraphs = val })
42 put (args, opts { groupDiff = val })
46 put (args, opts { benchType = val })
48-- Like the shell "shift" to shift the command line arguments
49shift :: StateT ([String], Options) (MaybeT IO) (Maybe String)
53 ([], _) -> return Nothing
54 (x : xs, opts) -> put (xs, opts) >> return (Just x)
56parseBench :: StateT ([String], Options) (MaybeT IO) ()
60 Just "linear" -> setBenchType Linear
61 Just "linear-async" -> setBenchType LinearAsync
62 Just "linear-rate" -> setBenchType LinearRate
63 Just "nested" -> setBenchType Nested
64 Just "base" -> setBenchType Base
66 liftIO $ putStrLn $ "unrecognized benchmark type " <> str
69 liftIO $ putStrLn "please provide a benchmark type "
72-- totally imperative style option parsing
73parseOptions :: IO (Maybe Options)
76 runMaybeT $ flip evalStateT (args, defaultOptions) $ do
84 "--graphs" -> setGenGraphs True
85 "--group-diff" -> setGroupDiff True
86 "--benchmark" -> parseBench
88 liftIO $ putStrLn $ "Unrecognized option " <> str
94 Just opt -> parseOpt opt >> parseLoop
97ignoringErr a = catch a (\(ErrorCall err :: ErrorCall) ->
98 putStrLn $ "Failed with error:\n" <> err <> "\nSkipping.")
100------------------------------------------------------------------------------
101-- Linear composition charts
102------------------------------------------------------------------------------
104makeLinearGraphs :: Config -> String -> IO ()
105makeLinearGraphs cfg@Config{..} inputFile = do
106 ignoringErr $ graph inputFile "generation" $ cfg
107 { title = (++) <$> title <*> Just " generation"
108 , classifyBenchmark =
109 fmap ("Streamly",) . stripPrefix "serially/generation/"
112 ignoringErr $ graph inputFile "elimination" $ cfg
113 { title = (++) <$> title <*> Just " Elimination"
114 , classifyBenchmark =
115 fmap ("Streamly",) . stripPrefix "serially/elimination/"
118 ignoringErr $ graph inputFile "transformation-zip" $ cfg
119 { title = (++) <$> title <*> Just " Transformation & Zip"
120 , classifyBenchmark = \b ->
121 if "serially/transformation/" `isPrefixOf` b
122 || "serially/zipping" `isPrefixOf` b
123 then Just ("Streamly", last $ splitOn "/" b)
127 ignoringErr $ graph inputFile "filtering" $ cfg
128 { title = (++) <$> title <*> Just " Filtering"
129 , classifyBenchmark =
130 fmap ("Streamly",) . stripPrefix "serially/filtering/"
133 ignoringErr $ graph inputFile "transformationX4" $ cfg
134 { title = (++) <$> title <*> Just " Transformation x 4"
135 , classifyBenchmark =
136 fmap ("Streamly",) . stripPrefix "serially/transformationX4/"
139 ignoringErr $ graph inputFile "filteringX4"
141 { title = (++) <$> title <*> Just " Filtering x 4"
142 , classifyBenchmark =
143 fmap ("Streamly",) . stripPrefix "serially/filteringX4/"
146 ignoringErr $ graph inputFile "mixedX4"
148 { title = (++) <$> title <*> Just " Mixed x 4"
149 , classifyBenchmark =
150 fmap ("Streamly",) . stripPrefix "serially/mixedX4/"
153 ignoringErr $ graph inputFile "iterated"
155 { title = Just "iterate 10,000 times over 10 elems"
156 , classifyBenchmark =
157 fmap ("Streamly",) . stripPrefix "serially/iterated/"
160------------------------------------------------------------------------------
161-- Nested composition charts
162------------------------------------------------------------------------------
164makeNestedGraphs :: Config -> String -> IO ()
165makeNestedGraphs cfg inputFile =
166 ignoringErr $ graph inputFile "nested-all" $ cfg
167 { presentation = Groups Absolute
168 , classifyBenchmark = classifyNested
169 , selectGroups = \gs ->
170 groupBy ((==) `on` snd) gs
171 & fmap (\xs -> mapMaybe (\x -> (x,) <$> lookup x xs) order)
177 order = ["serially", "asyncly", "wAsyncly", "aheadly", "parallely"]
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
192------------------------------------------------------------------------------
193-- Charts for parallel streams
194------------------------------------------------------------------------------
196makeLinearAsyncGraphs :: Config -> String -> IO ()
197makeLinearAsyncGraphs cfg inputFile =
198 ignoringErr $ graph inputFile "linear-async" cfg
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)
209 order = ["asyncly", "wAsyncly", "aheadly", "parallely"]
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
222makeLinearRateGraphs :: Config -> String -> IO ()
223makeLinearRateGraphs cfg inputFile = do
224 putStrLn "Not implemented"
227------------------------------------------------------------------------------
228-- Reports/Charts for base streams
229------------------------------------------------------------------------------
231showStreamDVsK Options{..} cfg inp out =
232 let cfg' = cfg { classifyBenchmark = classifyBase }
234 then ignoringErr $ graph inp "streamD-vs-streamK"
235 cfg' { outputDir = Just out
236 , presentation = Groups Absolute
238 else ignoringErr $ report inp Nothing cfg'
243 | "streamD/" `isPrefixOf` b = ("streamD",) <$> stripPrefix "streamD/" b
244 | "streamK/" `isPrefixOf` b = ("streamK",) <$> stripPrefix "streamK/" b
245 | otherwise = Nothing
247showStreamD Options{..} cfg inp out =
248 let cfg' = cfg { classifyBenchmark = classifyStreamD }
250 then ignoringErr $ graph inp "streamD"
251 cfg' {outputDir = Just out}
252 else ignoringErr $ report inp Nothing cfg'
257 | "streamD/" `isPrefixOf` b = ("streamD",) <$> stripPrefix "streamD/" b
258 | otherwise = Nothing
260showStreamK Options{..} cfg inp out =
261 let cfg' = cfg { classifyBenchmark = classifyStreamK }
263 then ignoringErr $ graph inp "streamK"
264 cfg' {outputDir = Just out}
265 else ignoringErr $ report inp Nothing cfg'
270 | "streamK/" `isPrefixOf` b = ("streamK",) <$> stripPrefix "streamK/" b
271 | otherwise = Nothing
273------------------------------------------------------------------------------
275------------------------------------------------------------------------------
277selectBench :: (SortColumn -> Either String [(String, Double)]) -> [String]
282 (const $ either error (sortOn snd) $ f $ ColumnIndex 0)
286benchShow Options{..} cfg func inp out =
288 then func cfg {outputDir = Just out} inp
289 else ignoringErr $ report inp Nothing cfg
293 let cfg = defaultConfig
294 { presentation = Groups PercentDiff
295 , selectBenchmarks = selectBench
301 putStrLn "cannot parse options"
303 Just opts@Options{..} ->
305 Linear -> benchShow opts cfg
306 { title = Just "100,000 elems" }
308 "charts/linear/results.csv"
310 LinearAsync -> benchShow opts cfg
311 { title = Just "Async 10,000 elems" }
312 makeLinearAsyncGraphs
313 "charts/linear-async/results.csv"
314 "charts/linear-async"
315 LinearRate -> benchShow opts cfg makeLinearRateGraphs
316 "charts/linear-rate/results.csv"
318 Nested -> benchShow opts cfg
319 { title = Just "Nested loops 100 x 100 elems" }
321 "charts/nested/results.csv"
324 let cfg' = cfg { title = Just "100,000 elems" }
326 then showStreamDVsK opts cfg'
327 "charts/base/results.csv"
330 showStreamD opts cfg'
331 "charts/base/results.csv"
333 showStreamK opts cfg'
334 "charts/base/results.csv"
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list