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------------------------------------------------------------------------------
38 , benchType :: BenchType
41defaultOptions = Options False False Linear
45 put (args, opts { genGraphs = val })
49 put (args, opts { groupDiff = val })
53 put (args, opts { benchType = val })
55-- Like the shell "shift" to shift the command line arguments
56shift :: StateT ([String], Options) (MaybeT IO) (Maybe String)
60 ([], _) -> return Nothing
61 (x : xs, opts) -> put (xs, opts) >> return (Just x)
63parseBench :: StateT ([String], Options) (MaybeT IO) ()
67 Just "linear" -> setBenchType Linear
68 Just "linear-async" -> setBenchType LinearAsync
69 Just "linear-rate" -> setBenchType LinearRate
70 Just "nested" -> setBenchType Nested
71 Just "base" -> setBenchType Base
72 Just "fileio" -> setBenchType FileIO
73 Just "array" -> setBenchType Array
75 liftIO $ putStrLn $ "unrecognized benchmark type " <> str
78 liftIO $ putStrLn "please provide a benchmark type "
81-- totally imperative style option parsing
82parseOptions :: IO (Maybe Options)
85 runMaybeT $ flip evalStateT (args, defaultOptions) $ do
93 "--graphs" -> setGenGraphs True
94 "--group-diff" -> setGroupDiff True
95 "--benchmark" -> parseBench
97 liftIO $ putStrLn $ "Unrecognized option " <> str
103 Just opt -> parseOpt opt >> parseLoop
106ignoringErr a = catch a (\(ErrorCall err :: ErrorCall) ->
107 putStrLn $ "Failed with error:\n" <> err <> "\nSkipping.")
109------------------------------------------------------------------------------
110-- Linear composition charts
111------------------------------------------------------------------------------
113makeLinearGraphs :: Config -> String -> IO ()
114makeLinearGraphs cfg@Config{..} inputFile = do
115 ignoringErr $ graph inputFile "generation" $ cfg
116 { title = (++) <$> title <*> Just " generation"
117 , classifyBenchmark =
118 fmap ("Streamly",) . stripPrefix "serially/generation/"
121 ignoringErr $ graph inputFile "elimination" $ cfg
122 { title = (++) <$> title <*> Just " Elimination"
123 , classifyBenchmark =
124 fmap ("Streamly",) . stripPrefix "serially/elimination/"
127 ignoringErr $ graph inputFile "transformation-zip" $ cfg
128 { title = (++) <$> title <*> Just " Transformation & Zip"
129 , classifyBenchmark = \b ->
130 if "serially/transformation/" `isPrefixOf` b
131 || "serially/zipping" `isPrefixOf` b
132 then Just ("Streamly", last $ splitOn "/" b)
136 ignoringErr $ graph inputFile "filtering" $ cfg
137 { title = (++) <$> title <*> Just " Filtering"
138 , classifyBenchmark =
139 fmap ("Streamly",) . stripPrefix "serially/filtering/"
142 ignoringErr $ graph inputFile "transformationX4" $ cfg
143 { title = (++) <$> title <*> Just " Transformation x 4"
144 , classifyBenchmark =
145 fmap ("Streamly",) . stripPrefix "serially/transformationX4/"
148 ignoringErr $ graph inputFile "filteringX4"
150 { title = (++) <$> title <*> Just " Filtering x 4"
151 , classifyBenchmark =
152 fmap ("Streamly",) . stripPrefix "serially/filteringX4/"
155 ignoringErr $ graph inputFile "mixedX4"
157 { title = (++) <$> title <*> Just " Mixed x 4"
158 , classifyBenchmark =
159 fmap ("Streamly",) . stripPrefix "serially/mixedX4/"
162 ignoringErr $ graph inputFile "iterated"
164 { title = Just "iterate 10,000 times over 10 elems"
165 , classifyBenchmark =
166 fmap ("Streamly",) . stripPrefix "serially/iterated/"
169------------------------------------------------------------------------------
170-- Nested composition charts
171------------------------------------------------------------------------------
173makeNestedGraphs :: Config -> String -> IO ()
174makeNestedGraphs cfg inputFile =
175 ignoringErr $ graph inputFile "nested-all" $ cfg
176 { presentation = Groups Absolute
177 , classifyBenchmark = classifyNested
178 , selectGroups = \gs ->
179 groupBy ((==) `on` snd) gs
180 & fmap (\xs -> mapMaybe (\x -> (x,) <$> lookup x xs) order)
186 order = ["serially", "asyncly", "wAsyncly", "aheadly", "parallely"]
189 | "serially/" `isPrefixOf` b =
190 ("serially",) <$> stripPrefix "serially/" b
191 | "asyncly/" `isPrefixOf` b =
192 ("asyncly",) <$> stripPrefix "asyncly/" b
193 | "wAsyncly/" `isPrefixOf` b =
194 ("wAsyncly",) <$> stripPrefix "wAsyncly/" b
195 | "aheadly/" `isPrefixOf` b =
196 ("aheadly",) <$> stripPrefix "aheadly/" b
197 | "parallely/" `isPrefixOf` b =
198 ("parallely",) <$> stripPrefix "parallely/" b
199 | otherwise = Nothing
201------------------------------------------------------------------------------
202-- Charts for parallel streams
203------------------------------------------------------------------------------
205makeLinearAsyncGraphs :: Config -> String -> IO ()
206makeLinearAsyncGraphs cfg inputFile =
207 ignoringErr $ graph inputFile "linear-async" cfg
208 { presentation = Groups Absolute
209 , classifyBenchmark = classifyAsync
210 , selectGroups = \gs ->
211 groupBy ((==) `on` snd) gs
212 & fmap (\xs -> mapMaybe (\x -> (x,) <$> lookup x xs) order)
218 order = ["asyncly", "wAsyncly", "aheadly", "parallely"]
221 | "asyncly/" `isPrefixOf` b =
222 ("asyncly",) <$> stripPrefix "asyncly/" b
223 | "wAsyncly/" `isPrefixOf` b =
224 ("wAsyncly",) <$> stripPrefix "wAsyncly/" b
225 | "aheadly/" `isPrefixOf` b =
226 ("aheadly",) <$> stripPrefix "aheadly/" b
227 | "parallely/" `isPrefixOf` b =
228 ("parallely",) <$> stripPrefix "parallely/" b
229 | otherwise = Nothing
231makeLinearRateGraphs :: Config -> String -> IO ()
232makeLinearRateGraphs cfg inputFile = do
233 putStrLn "Not implemented"
236------------------------------------------------------------------------------
238------------------------------------------------------------------------------
240makeFileIOGraphs :: Config -> String -> IO ()
241makeFileIOGraphs cfg@Config{..} inputFile =
242 ignoringErr $ graph inputFile "fileIO" cfg
244makeArrayGraphs :: Config -> String -> IO ()
245makeArrayGraphs cfg@Config{..} inputFile =
246 ignoringErr $ graph inputFile "array" cfg
248------------------------------------------------------------------------------
249-- Reports/Charts for base streams
250------------------------------------------------------------------------------
252showStreamDVsK Options{..} cfg inp out =
253 let cfg' = cfg { classifyBenchmark = classifyBase }
255 then ignoringErr $ graph inp "streamD-vs-streamK"
256 cfg' { outputDir = Just out
257 , presentation = Groups Absolute
259 else ignoringErr $ report inp Nothing cfg'
264 | "streamD/" `isPrefixOf` b = ("streamD",) <$> stripPrefix "streamD/" b
265 | "streamK/" `isPrefixOf` b = ("streamK",) <$> stripPrefix "streamK/" b
266 | otherwise = Nothing
268showStreamD Options{..} cfg inp out =
269 let cfg' = cfg { classifyBenchmark = classifyStreamD }
271 then ignoringErr $ graph inp "streamD"
272 cfg' {outputDir = Just out}
273 else ignoringErr $ report inp Nothing cfg'
278 | "streamD/" `isPrefixOf` b = ("streamD",) <$> stripPrefix "streamD/" b
279 | otherwise = Nothing
281showStreamK Options{..} cfg inp out =
282 let cfg' = cfg { classifyBenchmark = classifyStreamK }
284 then ignoringErr $ graph inp "streamK"
285 cfg' {outputDir = Just out}
286 else ignoringErr $ report inp Nothing cfg'
291 | "streamK/" `isPrefixOf` b = ("streamK",) <$> stripPrefix "streamK/" b
292 | otherwise = Nothing
294------------------------------------------------------------------------------
296------------------------------------------------------------------------------
299 :: (SortColumn -> Maybe GroupStyle -> Either String [(String, Double)])
305 (const $ either error (sortOn snd) $ f (ColumnIndex 0) (Just PercentDiff))
307 $ f (ColumnIndex 1) (Just PercentDiff)
309benchShow Options{..} cfg func inp out =
311 then func cfg {outputDir = Just out} inp
312 else ignoringErr $ report inp Nothing cfg
316 let cfg = defaultConfig
317 { presentation = Groups PercentDiff
318 , selectBenchmarks = selectBench
324 putStrLn "cannot parse options"
326 Just opts@Options{..} ->
328 Linear -> benchShow opts cfg
329 { title = Just "100,000 elems" }
331 "charts/linear/results.csv"
333 LinearAsync -> benchShow opts cfg
334 { title = Just "Async 10,000 elems" }
335 makeLinearAsyncGraphs
336 "charts/linear-async/results.csv"
337 "charts/linear-async"
338 LinearRate -> benchShow opts cfg makeLinearRateGraphs
339 "charts/linear-rate/results.csv"
341 Nested -> benchShow opts cfg
342 { title = Just "Nested loops 100 x 100 elems" }
344 "charts/nested/results.csv"
346 FileIO -> benchShow opts cfg
347 { title = Just "File IO" }
349 "charts/fileio/results.csv"
351 Array -> benchShow opts cfg
352 { title = Just "Array" }
354 "charts/array/results.csv"
357 let cfg' = cfg { title = Just "100,000 elems" }
359 then showStreamDVsK opts cfg'
360 "charts/base/results.csv"
363 showStreamD opts cfg'
364 "charts/base/results.csv"
366 showStreamK opts cfg'
367 "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