on master help sign in
Cleanup, fix issues in bench.sh
commit03218ad71b1ece35b86d9cbf4ae2a3a5a018cb8c authorHarendra Kumar <harendra@composewell.com> dateFri 4 Jun 2021, 14:09 (5 years ago) parentb68baf3
15 files changed+229−174
benchmark/README.md+25−14 benchmark/Streamly/Benchmark/Data/Array/Stream/Foreign.hs+2−2 benchmark/Streamly/Benchmark/Data/Parser.hs+3−13 benchmark/Streamly/Benchmark/Data/Parser/ParserD.hs+3−15 benchmark/Streamly/Benchmark/FileSystem/Handle.hs+2−2 benchmark/Streamly/Benchmark/Prelude/Concurrent.hs+12−2 benchmark/Streamly/Benchmark/Prelude/Rate.hs−1 benchmark/Streamly/Benchmark/Prelude/WAsync.hs+1−3 benchmark/Streamly/Benchmark/Prelude/ZipAsync.hs−1 benchmark/Streamly/Benchmark/Prelude/ZipSerial.hs+5−5 benchmark/lib/Streamly/Benchmark/Common.hs+28−26 benchmark/lib/Streamly/Benchmark/Common/Handle.hs+1−1 benchmark/streamly-benchmarks.cabal+3−3 bin/bench-exec-one.sh+76−38 bin/bench.sh+68−48
benchmark/README.md+25−14
@@ -1,3 +1,12 @@
1+# Benchmarking
2+
3+## Benchmark Dirvers
4+
5+Two benchmark drivers are supported:
6+
7+* `tasty-bench` (default)
8+* `gauge` (enabled by `--use-gauge` build flag)
9+
110## Building a single benchmark suite
211
312```
@@ -30,15 +39,18 @@ $ cabal build --flag "-opt" ...
3039
3140## Build and run single benchmarks:
3241
33−For quick results you may have to use `--quick` and possibly some other
34−`gauge` options, or better use `bench.sh --quick` as described in the
35−following sections.
42+The benchmark executables are `tasty-bench` executables unless you have
43+passed `--use-gauge` cabal flag when building in which case it is a
44+`gauge` executable.
45+
46+For quick results you may have to use a large value for `--stdev` or use
47+`bench.sh --quick` as described in the following sections.
3648
3749```
38−$ cabal run bench:Prelude.Serial -- --quick
50+$ cabal run bench:Prelude.Serial -- --stdev 100000
3951```
4052
41−`cabal bench` can be used but you cannot pass arguments (like --quick):
53+`cabal bench` can be used but you cannot pass arguments (like --stdev):
4254
4355```
4456$ cabal bench Prelude.Serial
@@ -104,7 +116,7 @@ $ bench.sh --benchmarks "Prelude.Serial Data.Parser"
104116Run all O(1) space complexity benchmarks in `Prelude.Serial` suite:
105117
106118```
107−$ bench.sh --benchmarks Prelude.Serial -- Prelude.Serial/o-1-space
119+$ bench.sh --benchmarks Prelude.Serial --prefix Prelude.Serial/o-1-space
108120```
109121
110122Anything after a `--` is passed to the benchmark executable,
@@ -114,13 +126,13 @@ it basically selects all benchmarks starting with
114126Run a specific benchmark in `Prelude.Serial` suite:
115127
116128```
117−$ bench.sh --benchmarks Prelude.Serial -- Prelude.Serial/o-1-space/generation/unfoldr
129+$ bench.sh --benchmarks Prelude.Serial --prefix Prelude.Serial/o-1-space/generation/unfoldr
118130```
119131
120132Run a benchmark directly instead of running it through `bench.sh`:
121133
122134```
123−$ cabal run bench:Prelude.Serial -- --quick Prelude.Serial/o-1-space/generation/unfoldr
135+$ cabal run bench:Prelude.Serial -- Prelude.Serial/o-1-space/generation/unfoldr
124136```
125137
126138The options after `--` are the benchmark executable options.
@@ -212,7 +224,7 @@ You can specify the stream size (default is 100000) to be used for
212224benchmarking:
213225
214226```
215−$ cabal run bench:Prelude.Serial -- --quick --stream-size 1000000
227+$ cabal run bench:Prelude.Serial -- --stream-size 1000000
216228```
217229
218230### Unicode input
@@ -222,7 +234,7 @@ environment variable:
222234
223235```
224236$ export Benchmark_FileSystem_Handle_InputFile=./gutenberg-500.txt
225−$ cabal run FileSystem.Handle -- --quick FileSystem.Handle/o-1-space/reduce/read/S.splitOnSeq
237+$ cabal run FileSystem.Handle -- FileSystem.Handle/o-1-space/reduce/read/S.splitOnSeq
226238```
227239
228240The automatic tests do not test unicode input, this option is useful to specify
@@ -230,10 +242,9 @@ a unicode text file manually.
230242
231243## Benchmarking notes
232244
233−We use gauge instead of criterion for benchmarking. We have fixed
234−several issues in gauge inherited from criterion. We have added several
235−features as well e.g. rusage stats, running benchmarks in an isolated
236−process etc which are crucial to our benchmarking analysis process.
245+We run each benchmark in an isolated process to minimize interference
246+of benchmarks and to be able to control the RTS memory restrictions per
247+benchmark.
237248
238249### Gotchas
239250
benchmark/Streamly/Benchmark/Data/Array/Stream/Foreign.hs+2−2
@@ -193,11 +193,11 @@ moduleName = "Data.Array.Stream.Foreign"
193193main :: IO ()
194194main = do
195195 env <- mkHandleBenchEnv
196− runWithCLIOpts defaultStreamSize (allBenchmarks env)
196+ defaultMain (allBenchmarks env)
197197
198198 where
199199
200− allBenchmarks env _ =
200+ allBenchmarks env =
201201 [ bgroup (o_1_space_prefix moduleName)
202202 ( o_1_space_read_chunked env
203203 ++ o_1_space_copy_toChunks_group_ungroup env
benchmark/Streamly/Benchmark/Data/Parser.hs+3−13
@@ -395,25 +395,15 @@ o_n_heap_serial value =
395395-- Driver
396396-------------------------------------------------------------------------------
397397
398−getArray :: (Int -> [Benchmark]) -> IO [Array.Array Int]
399−#ifndef MIN_VERSION_gauge
400−getArray f = do
401− (value, _) <- parseCLIOpts defaultStreamSize $ bgroup "All" (f 0)
402− IP.toList $ IP.arraysOf 100 $ sourceUnfoldrM value 0
403−#else
404−getArray _ = do
405− (value, _, _) <- parseCLIOpts defaultStreamSize
406− IP.toList $ IP.arraysOf 100 $ sourceUnfoldrM value 0
407−#endif
408−
409398main :: IO ()
410399main = do
411400 env <- mkHandleBenchEnv
412− arrays <- getArray (allBenchmarks env [])
413− runWithCLIOpts defaultStreamSize (allBenchmarks env arrays)
401+ runWithCLIOptsEnv defaultStreamSize alloc (allBenchmarks env)
414402
415403 where
416404
405+ alloc value = IP.toList $ IP.arraysOf 100 $ sourceUnfoldrM value 0
406+
417407 allBenchmarks env arrays value =
418408 [ bgroup (o_1_space_prefix moduleName) (o_1_space_serial value)
419409 , bgroup
benchmark/Streamly/Benchmark/Data/Parser/ParserD.hs+3−15
@@ -5,7 +5,6 @@
55-- License : BSD-3-Clause
66-- Maintainer : streamly@composewell.com
77
8−{-# LANGUAGE CPP #-}
98{-# LANGUAGE FlexibleContexts #-}
109{-# LANGUAGE ScopedTypeVariables #-}
1110{-# OPTIONS_GHC -fspec-constr-recursive=4 #-}
@@ -359,24 +358,13 @@ o_n_space_serial value =
359358-- Driver
360359-------------------------------------------------------------------------------
361360
362−getArray :: (Int -> [Benchmark]) -> IO [Array.Array Int]
363−#ifndef MIN_VERSION_gauge
364−getArray f = do
365− (value, _) <- parseCLIOpts defaultStreamSize $ bgroup "All" (f 0)
366− IP.toList $ IP.arraysOf 100 $ sourceUnfoldrM value 0
367−#else
368−getArray _ = do
369− (value, _, _) <- parseCLIOpts defaultStreamSize
370− IP.toList $ IP.arraysOf 100 $ sourceUnfoldrM value 0
371−#endif
372−
373361main :: IO ()
374−main = do
375− arrays <- getArray (allBenchmarks [])
376− runWithCLIOpts defaultStreamSize (allBenchmarks arrays)
362+main = runWithCLIOptsEnv defaultStreamSize alloc allBenchmarks
377363
378364 where
379365
366+ alloc value = IP.toList $ IP.arraysOf 100 $ sourceUnfoldrM value 0
367+
380368 allBenchmarks arraysSmall value =
381369 [ bgroup (o_1_space_prefix moduleName) (o_1_space_serial value)
382370 , bgroup (o_1_space_prefix moduleName) (o_1_space_serial_spanning value)
benchmark/Streamly/Benchmark/FileSystem/Handle.hs+2−2
@@ -44,11 +44,11 @@ moduleName = "FileSystem.Handle"
4444main :: IO ()
4545main = do
4646 env <- mkHandleBenchEnv
47− runWithCLIOpts defaultStreamSize (allBenchmarks env)
47+ defaultMain (allBenchmarks env)
4848
4949 where
5050
51− allBenchmarks env _ =
51+ allBenchmarks env =
5252 [ bgroup (o_1_space_prefix moduleName) $ Prelude.concat
5353 [ RO.allBenchmarks env
5454 , RW.allBenchmarks env
benchmark/Streamly/Benchmark/Prelude/Concurrent.hs+12−2
@@ -1,3 +1,5 @@
1+{-# LANGUAGE CPP #-}
2+{-# LANGUAGE RankNTypes #-}
13-- |
24-- Module : Main
35-- Copyright : (c) 2018 Composewell Technologies
@@ -5,8 +7,6 @@
57-- License : BSD3
68-- Maintainer : streamly@composewell.com
79
8−{-# LANGUAGE RankNTypes #-}
9−
1010import Control.Concurrent
1111import Control.Monad (when, replicateM)
1212import Streamly.Prelude
@@ -78,7 +78,17 @@ concatGroup buflen threads usec n =
7878
7979main :: IO ()
8080main =
81+#ifdef MIN_VERSION_gauge
82+ defaultMainWith (defaultConfig
83+ { timeLimit = Just 0
84+ , minSamples = Just 1
85+ , minDuration = 0
86+ , includeFirstIter = True
87+ , quickMode = True
88+ })
89+#else
8190 defaultMain
91+#endif
8292
8393 [ -- bgroup "append/buf-1-threads-10k-0sec" (appendGroup 1 10000 0)
8494 -- , bgroup "append/buf-100-threads-100k-0sec" (appendGroup 100 100000 0)
benchmark/Streamly/Benchmark/Prelude/Rate.hs−1
@@ -1,5 +1,4 @@
11{-# LANGUAGE FlexibleContexts #-}
2−{-# LANGUAGE CPP #-}
32
43-- |
54-- Module : Main
benchmark/Streamly/Benchmark/Prelude/WAsync.hs+1−3
@@ -5,8 +5,6 @@
55-- License : BSD3
66-- Maintainer : streamly@composewell.com
77
8−{-# LANGUAGE CPP #-}
9−
108import Prelude hiding (mapM)
119
1210import Streamly.Prelude (fromWAsync, fromSerial, wAsync, maxBuffer, maxThreads)
@@ -170,7 +168,7 @@ o_n_space_outerProduct value =
170168
171169main :: IO ()
172170main = runWithCLIOpts defaultStreamSize allBenchmarks
173−
171+
174172 where
175173
176174 allBenchmarks value =
benchmark/Streamly/Benchmark/Prelude/ZipAsync.hs−1
@@ -6,7 +6,6 @@
66-- Maintainer : streamly@composewell.com
77
88{-# LANGUAGE FlexibleContexts #-}
9−{-# LANGUAGE CPP #-}
109
1110import Streamly.Prelude (fromSerial)
1211import qualified Streamly.Prelude as S
benchmark/Streamly/Benchmark/Prelude/ZipSerial.hs+5−5
@@ -60,8 +60,8 @@ zipWith count n =
6060 S.drain $
6161 S.zipWith
6262 (,)
63− (S.fromSerial $ Main.sourceUnfoldrM count n)
64− (S.fromSerial $ Main.sourceUnfoldrM count (n + 1))
63+ (S.fromSerial $ sourceUnfoldrM count n)
64+ (S.fromSerial $ sourceUnfoldrM count (n + 1))
6565
6666#ifdef INSPECTION
6767inspect $ hasNoTypeClasses 'zipWith
@@ -75,8 +75,8 @@ zipWithM count n =
7575 S.drain $
7676 S.zipWithM
7777 (curry return)
78− (Main.sourceUnfoldrM count n)
79− (Main.sourceUnfoldrM count (n + 1))
78+ (sourceUnfoldrM count n)
79+ (sourceUnfoldrM count (n + 1))
8080
8181#ifdef INSPECTION
8282inspect $ hasNoTypeClasses 'zipWithM
@@ -125,7 +125,7 @@ o_1_space_outerProduct value =
125125-- passed using the --stream-size option.
126126--
127127main :: IO ()
128−main = runWithCLIOpts defaultStreamSize allBenchmarks
128+main = runWithCLIOpts defaultStreamSize allBenchmarks
129129
130130 where
131131
benchmark/lib/Streamly/Benchmark/Common.hs+28−26
@@ -16,8 +16,7 @@ module Streamly.Benchmark.Common
1616 , o_n_heap_prefix
1717 , o_n_stack_prefix
1818
19− -- , parseEnvOpts
20− , parseCLIOpts
19+ , runWithCLIOptsEnv
2120 , runWithCLIOpts
2221
2322 , benchIOSink1
@@ -33,14 +32,6 @@ module Streamly.Benchmark.Common
3332 , mkListString
3433
3534 , defaultStreamSize
36− , BenchOpts(..)
37−#ifndef MIN_VERSION_gauge
38− , OptionDescription(..)
39− , includingOptions
40− , lookupOption
41− , defaultMainWithIngredients
42− , parseOptions
43−#endif
4435 )
4536where
4637
@@ -54,10 +45,11 @@ import System.Console.GetOpt
5445 (OptDescr(..), ArgDescr(..), ArgOrder(..), getOpt')
5546import System.Environment (getArgs, lookupEnv, setEnv)
5647#else
57−import Data.Proxy
58−import Test.Tasty.Ingredients.Basic
48+import Data.Proxy (Proxy(..))
49+import Test.Tasty.Ingredients.Basic (includingOptions)
5950import Test.Tasty.Options
60−import Test.Tasty.Runners
51+ (IsOption(..), OptionDescription(..), lookupOption, safeRead)
52+import Test.Tasty.Runners (Ingredient, defaultMainWithIngredients, parseOptions)
6153#endif
6254import Control.DeepSeq (NFData(..))
6355import Data.Functor.Identity (Identity, runIdentity)
@@ -230,27 +222,37 @@ instance IsOption BenchOpts where
230222 defaultValue = StreamSize defaultStreamSize
231223 parseValue = fmap StreamSize . safeRead
232224 optionName = pure "stream-size"
233− optionHelp = pure "StreamSize used in benchmarks"
225+ optionHelp = pure "Size of the stream to be used in benchmarks"
234226
235227parseCLIOpts :: Int -> Benchmark -> IO (Int, [Ingredient])
236−parseCLIOpts cDefSize benches = do
228+parseCLIOpts defStreamSize benches = do
237229 let customOpts = [Test.Tasty.Options.Option (Proxy :: Proxy BenchOpts)]
238230 ingredients = includingOptions customOpts : benchIngredients
239− opts <- parseOptions ingredients benches
231+ opts <- parseOptions ingredients benches -- (TestGroup "" [])
240232 let StreamSize size = lookupOption opts
241− print $ "Stream-Size = " ++ show size
242− if size == defaultStreamSize -- LONG option is not set
243− then return (cDefSize, ingredients) -- use custom defaut size of Benchmark
244− else return (size, ingredients) -- LONG option is set use large stream size
233+ -- putStrLn $ "Stream size: " ++ show size
234+ if size == defaultStreamSize
235+ then return (defStreamSize, ingredients)
236+ else return (size, ingredients)
245237#endif
246238
247−runWithCLIOpts :: Int -> (Int -> [Benchmark]) -> IO ()
248−runWithCLIOpts cDefSize f = do
239+runWithCLIOptsEnv :: Int -> (Int -> IO a) -> (a -> Int -> [Benchmark]) -> IO ()
240+runWithCLIOptsEnv defStreamSize alloc mkBench = do
249241
250242#ifdef MIN_VERSION_gauge
251− (value, cfg, benches) <- parseCLIOpts cDefSize
252− value `seq` runMode (mode cfg) cfg benches (f value)
243+ (value, cfg, benches) <- parseCLIOpts defStreamSize
244+ r <- alloc value
245+ value `seq` runMode (mode cfg) cfg benches (mkBench r value)
253246#else
254− (value, ingredients) <- parseCLIOpts cDefSize $ bgroup "All" (f 0)
255− value `seq` defaultMainWithIngredients ingredients $ bgroup "All" (f value)
247+ (value, ingredients) <-
248+ parseCLIOpts defStreamSize $ bgroup "All" (mkBench undefined 0)
249+ r <- alloc value
250+ value `seq` defaultMainWithIngredients ingredients
251+ $ bgroup "All" (mkBench r value)
256252#endif
253+
254+runWithCLIOpts :: Int -> (Int -> [Benchmark]) -> IO ()
255+runWithCLIOpts defStreamSize f =
256+ runWithCLIOptsEnv defStreamSize
257+ (const $ return undefined)
258+ (\_ v -> f v)
benchmark/lib/Streamly/Benchmark/Common/Handle.hs+1−1
@@ -106,7 +106,7 @@ getHandles env mkHandles = do
106106 }
107107
108108 -- update
109− writeIORef (href env) $ refHandles
109+ writeIORef (href env) refHandles
110110 return $ mkHandles refHandles
111111
112112mkBenchCommon ::
benchmark/streamly-benchmarks.cabal+3−3
@@ -124,13 +124,13 @@ common bench-depends
124124 , directory >= 1.2.2 && < 1.4
125125 , ghc-prim >= 0.4 && < 0.8
126126
127− if flag(use-gauge)
127+ if flag(use-gauge)
128128 build-depends: gauge >= 0.2.4 && < 0.3
129− else
129+ else
130130 build-depends: tasty-bench >= 0.2.5 && < 0.3
131131 , tasty >= 1.4.1
132132 mixins: tasty-bench
133− (Test.Tasty.Bench as Gauge
133+ (Test.Tasty.Bench as Gauge
134134 , Test.Tasty.Bench as Gauge.Main
135135 )
136136
bin/bench-exec-one.sh+76−38
@@ -4,6 +4,8 @@
44# BENCH_EXEC_PATH: the benchmark executable
55# RTS_OPTIONS: additional RTS options
66# QUICK_MODE: whether we are in quick mode
7+# USE_GAUGE: whether to use gauge or tasty-bench
8+# LONG: whether to use a large stream size
79
810# $1: message
911die () {
@@ -42,6 +44,9 @@ bench_rts_opts_default () {
4244}
4345
4446# Overrides for specific benchmarks
47+# XXX Note: for tasty-bench we replace the "." separator in the benchmark names
48+# with "/" for matching with this. It may not work reliably if the benchmark
49+# name already contains ".".
4550bench_rts_opts_specific () {
4651 case "$1" in
4752 Data.Stream.StreamD/o-n-space/elimination/toList) echo -n "-K2M" ;;
@@ -103,43 +108,46 @@ bench_rts_opts_specific () {
103108if test "$USE_GAUGE" -eq 0
104109then
105110 SUPER_QUICK_OPTIONS="--stdev 1000000"
106− QUICKER_OPTIONS="--stdev 1000"
111+ QUICKER_OPTIONS="--stdev 100"
107112else
108113 # Do not keep time limit as 0 otherwise GC stats may remain 0 in some cases.
109114 SUPER_QUICK_OPTIONS="--quick --min-duration 0 --time-limit 0.01 --include-first-iter"
110115 QUICKER_OPTIONS="--min-samples 3 --time-limit 1"
111116fi
112117
118+# tasty-bench does not like an option set twice
119+set_super_quick_mode () {
120+ echo -n super_quick
121+}
122+
113123# For certain long benchmarks if the user has not requested super quick
114124# mode we anyway use a slightly quicker mode.
115125use_quicker_mode () {
116− if test -n "$QUICK_MODE"
126+ if test "$QUICK_MODE" -eq 0
117127 then
118− if test "$QUICK_MODE" -eq 0
119− then
120− echo $QUICKER_OPTIONS
121− fi
128+ echo quicker
122129 fi
123130}
124131
125132bench_exe_quick_opts () {
126133 case "$1" in
127− Prelude.Concurrent) echo -n "$SUPER_QUICK_OPTIONS" ;;
128− Prelude.Rate) echo -n "$SUPER_QUICK_OPTIONS" ;;
129− Prelude.Adaptive) echo -n "$SUPER_QUICK_OPTIONS" ;;
134+ Prelude.Concurrent) set_super_quick_mode ;;
135+ Prelude.Rate) set_super_quick_mode ;;
136+ Prelude.Adaptive) set_super_quick_mode;;
130137 *) echo -n "" ;;
131138 esac
132139}
133140
141+# XXX Note: for tasty-bench we replace the "." separator in the benchmark names
142+# with "/" for matching with this. It may not work reliably if the benchmark
143+# name already contains ".".
144+
134145# Use quick options for benchmarks that take too long
135146bench_quick_opts () {
136147 case "$1" in
137− Prelude.Parallel/o-n-heap/mapping/mapM)
138− echo -n "$SUPER_QUICK_OPTIONS" ;;
139− Prelude.Parallel/o-n-heap/monad-outer-product/*)
140− echo -n "$SUPER_QUICK_OPTIONS" ;;
141− Prelude.Parallel/o-n-space/monad-outer-product/*)
142− echo -n "$SUPER_QUICK_OPTIONS" ;;
148+ Prelude.Parallel/o-n-heap/mapping/mapM) set_super_quick_mode ;;
149+ Prelude.Parallel/o-n-heap/monad-outer-product/*) set_super_quick_mode ;;
150+ Prelude.Parallel/o-n-space/monad-outer-product/*) set_super_quick_mode ;;
143151 Prelude.Parallel/o-n-heap/generation/*) use_quicker_mode ;;
144152 Prelude.Parallel/o-n-heap/mapping/*) use_quicker_mode ;;
145153 Prelude.Parallel/o-n-heap/concat-foldable/*) use_quicker_mode ;;
@@ -163,11 +171,12 @@ bench_output_file() {
163171 echo "charts/$bench_name/results.csv"
164172}
165173
166−BENCH_NAME_ORIG=""
167−for i in "$@"
168−do
169− BENCH_NAME_ORIG="$i"
170−done
174+#------------------------------------------------------------------------------
175+# Determine options from benchmark name
176+#------------------------------------------------------------------------------
177+
178+BENCH_NAME_ORIG="$1"
179+shift
171180
172181if test "$USE_GAUGE" -eq 0
173182then
@@ -178,16 +187,8 @@ then
178187 BENCH_NAME1=$(echo $BENCH_NAME | cut -f1 -d '/')
179188 BENCH_NAME2=$(echo $BENCH_NAME | cut -f2- -d '/' | sed -e 's/\./\//g')
180189 BENCH_NAME="$BENCH_NAME1/$BENCH_NAME2"
181− JOB_OPT=" -j 1"
182190else
183191 BENCH_NAME=$BENCH_NAME_ORIG
184− JOB_OPT=""
185−fi
186−if test "$LONG" -eq 0
187−then
188− SIZE_OPT=""
189−else
190− SIZE_OPT="--stream-size 1000000"
191192fi
192193
193194RTS_OPTIONS=\
@@ -198,28 +199,65 @@ $(bench_rts_opts_specific $BENCH_NAME) \
198199$RTS_OPTIONS \
199200-RTS"
200201
201−QUICK_BENCH_OPTIONS="\
202−$(if test "$QUICK_MODE" -ne 0; then echo $SUPER_QUICK_OPTIONS; else :; fi)
202+QUICK_MODE_TYPE="\
203+$(if test "$QUICK_MODE" -ne 0; then set_super_quick_mode; fi) \
203204$(bench_exe_quick_opts $(basename $BENCH_EXEC_PATH)) \
204205$(bench_quick_opts $BENCH_NAME)"
205206
206−output_file=$(bench_output_file $(basename $BENCH_EXEC_PATH))
207−mkdir -p `dirname $output_file`
207+for i in $QUICK_MODE_TYPE
208+do
209+ case "$i" in
210+ super_quick) QUICK_BENCH_OPTIONS="$SUPER_QUICK_OPTIONS"; break ;;
211+ quicker) QUICK_BENCH_OPTIONS="$QUICKER_OPTIONS"; break ;;
212+ esac
213+done
214+
215+if test "$LONG" -ne 0
216+then
217+ STREAM_SIZE=10000000
218+ STREAM_LEN=$(env LC_ALL=en_US.UTF-8 printf "--stream-size %'.f\n" $STREAM_SIZE)
219+ STREAM_SIZE_OPT="--stream-size $STREAM_SIZE"
220+fi
208221
209222echo "$BENCH_NAME: \
210−$QUICK_BENCH_OPTIONS \
211−$RTS_OPTIONS"
223+$RTS_OPTIONS \
224+$STREAM_LEN \
225+$QUICK_BENCH_OPTIONS" \
226+"$@"
212227
228+#------------------------------------------------------------------------------
229+# Run benchmark with options and collect results
230+#------------------------------------------------------------------------------
231+
232+output_file=$(bench_output_file $(basename $BENCH_EXEC_PATH))
233+mkdir -p `dirname $output_file`
213234rm -f ${output_file}.tmp
235+
214236if test $USE_GAUGE -eq 0
215237then
238+ # Escape "\" and double quotes in benchmark names
216239 BENCH_NAME_ESC=$(echo "$BENCH_NAME_ORIG" | sed -e 's/\\/\\\\/g' | sed -e 's/"/\\"/g')
217− $BENCH_EXEC_PATH $SIZE_OPT $JOB_OPT $RTS_OPTIONS $QUICK_BENCH_OPTIONS --csv=${output_file}.tmp \
240+ $BENCH_EXEC_PATH \
241+ -j 1 \
242+ $RTS_OPTIONS \
243+ $STREAM_SIZE_OPT \
244+ $QUICK_BENCH_OPTIONS \
245+ "$@" \
246+ --csv=${output_file}.tmp \
218247 -p '$0 == "'"$BENCH_NAME_ESC"'"'
248+
249+ # Convert cpuTime field from picoseconds to seconds
219250 tail -n +2 ${output_file}.tmp | \
220− awk 'BEGIN {FPAT = "([^,]+)|(\"[^\"]+\")";OFS=","} {$2=$2/1000000000000;print}' >> $output_file
251+ awk 'BEGIN {FPAT = "([^,]+)|(\"[^\"]+\")";OFS=","} {$2=$2/1000000000000;print}' \
252+ >> $output_file
221253else
222− $BENCH_EXEC_PATH $SIZE_OPT $RTS_OPTIONS $QUICK_BENCH_OPTIONS --csvraw=${output_file}.tmp \
254+ $BENCH_EXEC_PATH \
255+ $RTS_OPTIONS \
256+ $STREAM_SIZE_OPT \
257+ $QUICK_BENCH_OPTIONS \
258+ "$@" \
259+ --csvraw=${output_file}.tmp \
223260 -m exact "$BENCH_NAME"
224− tail -n +2 ${output_file}.tmp >> $output_file
261+ tail -n +2 ${output_file}.tmp \
262+ >> $output_file
225263fi
bin/bench.sh+68−48
@@ -8,6 +8,7 @@ source $SCRIPT_DIR/build-lib.sh
88print_help () {
99 echo "Usage: $0 "
1010 echo " [--benchmarks <"bench1 bench2 ..." | help>]"
11+ echo " [--prefix <benchmark name prefix to match>"
1112 echo " [--fields <"field1 field2 ..." | help>]"
1213 echo " [--graphs]"
1314 echo " [--no-measure]"
@@ -142,11 +143,58 @@ bench_output_file() {
142143 echo "charts/$bench_name/results.csv"
143144}
144145
146+invoke_gauge () {
147+ local target_prog="$1"
148+ local target_name="$2"
149+ local output_file="$3"
150+
151+ local MATCH=""
152+ if test "$LONG" -ne 0
153+ then
154+ MATCH="$target_name/o-1-space"
155+ else
156+ MATCH="$BENCH_PREFIX"
157+ fi
158+ echo "name,iters,time,cycles,cpuTime,utime,stime,maxrss,minflt,majflt,nvcsw,nivcsw,allocated,numGcs,bytesCopied,mutatorWallSeconds,mutatorCpuSeconds,gcWallSeconds,gcCpuSeconds" >> $output_file
159+ # keep only benchmark names with shortest prefix e.g. "a/b/c" and "a/b", we
160+ # should only keep "a/b" otherwise benchmarks will run multiple times. why?
161+ $target_prog -l \
162+ | grep "^$target_name" \
163+ | grep "^$MATCH" \
164+ | sort \
165+ | awk 'BEGIN {prev="XXX"} {if (substr($0,1,length(prev)) != prev) {print $0; prev=$0}}' \
166+ | while read -r name; \
167+ do bin/bench-exec-one.sh "$name" "${GAUGE_ARGS[@]}"; done
168+}
169+
170+invoke_tasty_bench () {
171+ local target_prog="$1"
172+ local target_name="$2"
173+ local output_file="$3"
174+
175+ local MATCH=""
176+ if test "$LONG" -ne 0
177+ then
178+ MATCH="-p /$target_name\/o-1-space/"
179+ else
180+ if test -n "$BENCH_PREFIX"
181+ then
182+ # escape "/"
183+ local escaped_name=$(echo "$BENCH_PREFIX" | sed -e 's/\//\\\//g')
184+ MATCH="-p /$escaped_name/"
185+ fi
186+ fi
187+ echo "Name,cpuTime,2*Stdev (ps),Allocated,bytesCopied" >> $output_file
188+ $target_prog -l $MATCH \
189+ | grep "^All" \
190+ | while read -r name; \
191+ do bin/bench-exec-one.sh "$name" "${GAUGE_ARGS[@]}"; done
192+}
193+
145194run_bench_target () {
146195 local package_name=$1
147196 local component=$2
148197 local target_name=$3
149− local output_file=$(bench_output_file $target_name)
150198
151199 local target_prog
152200 target_prog=$(cabal_target_prog $package_name $component $target_name) || \
@@ -156,46 +204,16 @@ run_bench_target () {
156204
157205 # Needed by bench-exec-one.sh
158206 export BENCH_EXEC_PATH=$target_prog
159− if test "$LONG" -ne 0
160− then
161− BENCH_ARGS="-p /$target_name\/o-1-space/"
162− STREAM_SIZE=10000000
163− export STREAM_SIZE
164− fi
207+ export RTS_OPTIONS
208+ export QUICK_MODE
209+ export USE_GAUGE
210+ export LONG
165211
166− local MATCH=""
212+ local output_file=$(bench_output_file $target_name)
213+ mkdir -p `dirname $output_file`
167214 if test "$USE_GAUGE" -eq 0
168− then
169− if test "$LONG" -ne 0
170− then
171− MATCH="-p /$target_name\/o-1-space/"
172− else
173− if test -n "$GAUGE_ARGS"
174− then
175− local GAUGE_ARGS1=$(echo "$GAUGE_ARGS" | sed -e 's/\//\\\//g')
176− MATCH="-p /$GAUGE_ARGS1/"
177− fi
178− fi
179− echo "Name,cpuTime,2*Stdev (ps),Allocated,bytesCopied" >> $output_file
180− $target_prog -l $MATCH \
181− | grep "^All" \
182− | while read -r name; do bin/bench-exec-one.sh "$name"; done
183− else
184− if test "$LONG" -ne 0
185− then
186− MATCH="$target_name/o-1-space"
187− else
188− MATCH="$GAUGE_ARGS"
189− fi
190− echo "name,iters,time,cycles,cpuTime,utime,stime,maxrss,minflt,majflt,nvcsw,nivcsw,allocated,numGcs,bytesCopied,mutatorWallSeconds,mutatorCpuSeconds,gcWallSeconds,gcCpuSeconds" >> $output_file
191− # XXX We may have to use "sort | awk" to keep only benchmark names with
192− # shortest prefix e.g. "a/b/c" and "a/b", we should only keep "a/b"
193− # otherwise benchmarks will run multiple times.
194− $target_prog -l \
195− | grep "^$target_name" \
196− | grep "^$MATCH" \
197− | sort | paste -sd "," - | awk 'BEGIN {FS=","} {t="XU987"; for(i=1;i<=NF;i++) if (substr($i,1,length(t)) != t) {print $i; t=$i}}' \
198− | while read -r name; do bin/bench-exec-one.sh "$name"; done
215+ then invoke_tasty_bench "$target_prog" "$target_name" "$output_file"
216+ else invoke_gauge "$target_prog" "$target_name" "$output_file"
199217 fi
200218}
201219
@@ -284,7 +302,6 @@ run_reports() {
284302cd $SCRIPT_DIR/..
285303
286304USE_GAUGE=0
287−export USE_GAUGE
288305USE_GIT_CABAL=1
289306set_common_vars
290307
@@ -318,6 +335,7 @@ do
318335 # options with arguments
319336 --benchmarks) shift; TARGETS=$1; shift ;;
320337 --targets) shift; TARGETS=$1; shift ;;
338+ --prefix) shift; BENCH_PREFIX="$1" shift ;;
321339 --fields) shift; FIELDS=$1; shift ;;
322340 --base) shift; BASE=$1; shift ;;
323341 --candidate) shift; CANDIDATE=$1; shift ;;
@@ -334,13 +352,13 @@ do
334352 --long) LONG=1; shift ;;
335353 --graphs) GRAPH=1; shift ;;
336354 --no-measure) MEASURE=0; shift ;;
337− --dev-build) RUNNING_DEVBUILD=1; shift ;;
355+ --dev-build) RUNNING_DEVBUILD=1; shift ;;
356+ --use-gauge) USE_GAUGE=1; shift ;;
338357 --) shift; break ;;
339− -*|--*) echo "Unknown flags: $*"; echo; print_help ;;
340− *) break ;;
358+ *) echo "Unknown flags: $*"; echo; print_help ;;
341359 esac
342360done
343−GAUGE_ARGS=$*
361+GAUGE_ARGS=("$@")
344362
345363set_derived_vars
346364
@@ -414,13 +432,15 @@ build_report_progs
414432# Build and run targets
415433#-----------------------------------------------------------------------------
416434
417−BUILD_BENCH="$CABAL_EXECUTABLE v2-build $CABAL_BUILD_OPTIONS --enable-benchmarks"
435+if test "$USE_GAUGE" -eq 1
436+then
437+ BUILD_FLAGS="--flag use-gauge"
438+fi
439+
440+BUILD_BENCH="$CABAL_EXECUTABLE v2-build $BUILD_FLAGS $CABAL_BUILD_OPTIONS --enable-benchmarks"
418441if test "$MEASURE" = "1"
419442then
420443 run_build "$BUILD_BENCH" streamly-benchmarks bench "$TARGETS"
421− export QUICK_MODE
422− export RTS_OPTIONS
423− export LONG
424444 run_measurements "$TARGETS"
425445fi
426446