Skip to content

Commit 39d7899

Browse files
authored
Merge pull request ucsd-progsys#2177 from clayrat/plot-performance
Better performance plotting script and readme updates
2 parents 4693b67 + 32de722 commit 39d7899

File tree

11 files changed

+455
-76
lines changed

11 files changed

+455
-76
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ tests/**/*.dyn_o
5959
tests/**/*.hi-boot
6060
tests/**/*.o-boot
6161

62+
tmp/
63+
*.svg
64+
6265
.idea
6366
*.iml
6467

README.md

Lines changed: 43 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ to let us know. If possible, try to:
2525

2626
## Your first Pull Request
2727

28-
We are thrilled to get PRs! Please follow these guidelines, as doing so will increase the chances of
28+
We are thrilled to get PRs! Please follow these guidelines, as doing so will increase the chances of
2929
having your PR accepted:
3030

3131
* The main LH repo [lives here](https://github.com/ucsd-progsys/liquidhaskell)
@@ -98,7 +98,7 @@ It's also possible (but not recommended) to add `LIQUID_DEV_MODE` to .bashrc or
9898
permanently disable building the `liquid-*` packages, and this might silently mask breaking changes to the
9999
`liquidhaskell` library that would manifest only when compiling these other packages.
100100

101-
If you wish to force building all the libraries again, it's sufficient to issue the same builds commands
101+
If you wish to force building all the libraries again, it's sufficient to issue the same builds commands
102102
without the `LIQUID_DEV_MODE`.
103103

104104
## How To Run Regression Tests
@@ -115,7 +115,7 @@ You can run a bunch of particular test-groups instead by
115115

116116
$ LIQUID_DEV_MODE=true ./scripts/test/test_plugin.sh <test-group-name1> <test-group-name2> ...
117117

118-
and you can list all the possible test options with
118+
and you can list all the possible test options with
119119

120120
$ LIQUID_DEV_MODE=true ./scripts/test/test_plugin.sh --help
121121

@@ -147,8 +147,8 @@ When `liquidhaskell` tests run, we can collect timing information with
147147

148148
$ ./scripts/test/test_plugin.sh --measure-timings
149149

150-
Measures will be collected in `.dump-timings` files. These can be converted to json
151-
data with
150+
Measures will be collected in `.dump-timings` files under `dist-newstyle` directory. These can be
151+
converted to json data with
152152

153153
```bash
154154
cabal v2-build ghc-timings
@@ -163,16 +163,26 @@ cabal v2-run benchmark-timings -- tmp/*.json --phase LiquidHaskell -o summary.cs
163163
```
164164
On each line, the report will contain the time taken by each test.
165165

166-
There is a script `scripts/plot-performance/chart_perf.sh` that can be
167-
used to generate comparison charts in `svg` and `png` formats. It
168-
requires [gnuplot](http://www.gnuplot.info/) to run. The following
169-
command will produce two files `perf.svg` and `perf.png` in the
170-
current directory.
166+
Comparison charts in `svg` format can be generated by invoking
167+
168+
```
169+
cabal v2-run plot-performance -- -b path_to_before_summary.csv -a path_to_after_summary.csv -s 50 -f "benchmark" -o outdir
170+
```
171+
172+
This will generate three files `filtered.svg` (a subset of tests with a `benchmark` prefix, enabled by the `-f` option),
173+
`top.svg` and `bot.svg` (top 50 speedups and slowdowns over the entire test set, both enabled by the `-s` option) under
174+
the `outdir` directory. The `-f` and `-s` options can be used/omitted independently. If both are omitted, a single
175+
`perf.svg` will be produced covering the full input test set. Additionally, their effects can be combined by providing
176+
a third `-c` option (this will produce 2 files `filtered-top.svg` and `filtered-bot.svg` instead of 3).
177+
178+
There is also a legacy script `scripts/plot-performance/chart_perf.sh` that can be used to generate comparison charts
179+
in both `svg` and `png` formats. It requires [gnuplot](http://www.gnuplot.info/) to run and assumes both files contain
180+
the same test set. The following command will produce two files `perf.svg` and `perf.png` in the current directory.
171181

172182
$ scripts/plot-performance/chart_perf.sh path_to_before_summary.csv path_to_after_summary.csv
173183

174-
The current formatting is optimized for comparing the outputs of running
175-
the benchmarks alone.
184+
The current formatting is optimized for comparing some subsets of the full test run, typically just the benchmarks alone.
185+
If one wishes to save time or is not interested in top speedups/slowdowns, the benchmark subset can be obtained by running
176186

177187
$ scripts/test/test_plugin.sh \
178188
benchmark-stitch-lh \
@@ -185,7 +195,7 @@ the benchmarks alone.
185195

186196
## Miscelaneous tasks
187197

188-
* **Profiling** See the instructions in [scripts/ProfilingDriver.hs][].
198+
* **Profiling** See the instructions in [scripts/ProfilingDriver.hs](scripts/ProfilingDriver.hs).
189199
* **Getting stack traces on exceptions** See `-xc` flag in the [GHC user's guide][ghc-users-guide].
190200
* **Working with submodules** See `man gitsubmodules` or the [git documentation site][git-documentation].
191201

@@ -338,7 +348,7 @@ any `LiftedSpec` from the interface file's annotations.
338348
Typically the first thing you might want to do is to run a "clean" `cabal v2-build` or `stack build` using
339349
the latest compiler and "check the damage". If you are lucky, everything works out of the box, otherwise
340350
compilation might fail with an error, typically because some `ghc` API function has been removed/moved/renamed.
341-
The way to fix it is to modify the [GHC.API][] shim module and perform any required change, likely by
351+
The way to fix it is to modify the [GHC.API][] shim module and perform any required change, likely by
342352
conditionally compiling some code in a `CPP` block. For minor changes, it's usually enough to perform small
343353
changes, but for more tricky migrations it might be necessary to backport some GHC code, or create some
344354
patter synonym to deal with changes in type constructors.
@@ -348,8 +358,6 @@ patter synonym to deal with changes in type constructors.
348358
Currently, no. Only one version of GHC is supported and that is the one
349359
that can be tested with `./scripts/test/test_plugin.sh`.
350360

351-
[GHC.API]: src-ghc/Liquid/GHC/API.hs
352-
353361
# GHC Plugin Development FAQs
354362

355363
## Why is the GHC.Interface using slightly different types than the GHC.Plugin module?
@@ -361,24 +369,24 @@ to map back and forth (sometimes in a partial way) between old and new data stru
361369
**consider the GHC.Plugin as the single source of truth, and prefer whichever data structure the latter is
362370
using**.
363371

364-
365-
[Plugin]: src/Language/Haskell/Liquid/GHC/Plugin.hs
366-
[GHC.Plugin]: src/Language/Haskell/Liquid/GHC/Plugin.hs
367-
[GHC.Interface]: src-ghc/Liquid/GHC/Interface.hs
368-
[SpecFinder]: src/Language/Haskell/Liquid/GHC/Plugin/SpecFinder.hs
369-
[BareSpec]: src/Language/Haskell/Liquid/Types/Specs.hs#L361
370-
[LiftedSpec]: src/Language/Haskell/Liquid/Types/Specs.hs#L554
371-
[TargetSrc]: src/Language/Haskell/Liquid/Types/Specs.hs#L157
372-
[Ghc monad]: https://hackage.haskell.org/package/ghc-8.10.1/docs/GHC.html#t:Ghc
373-
[HscEnv]: https://hackage.haskell.org/package/ghc-8.10.1/docs/GHC.html#t:HscEnv
374-
[DynFlags]: https://hackage.haskell.org/package/ghc-8.10.1/docs/GHC.html#t:DynFlags
375-
[GhcMonad]: https://hackage.haskell.org/package/ghc-8.10.1/docs/GHC.html#t:GhcMonad
376-
[GhcMonadLike]: src-ghc/Liquid/GHC/GhcMonadLike.hs
377-
[typechecking phase]: src/Language/Haskell/Liquid/GHC/Plugin.hs#L206-L222
372+
[GHC.API]: liquidhaskell-boot/src-ghc/Liquid/GHC/API.hs
373+
[Plugin]: liquidhaskell-boot/src/Language/Haskell/Liquid/GHC/Plugin.hs
374+
[GHC.Plugin]: liquidhaskell-boot/src/Language/Haskell/Liquid/GHC/Plugin.hs
375+
[GHC.Interface]: liquidhaskell-boot/src-ghc/Liquid/GHC/Interface.hs
376+
[SpecFinder]: liquidhaskell-boot/src/Language/Haskell/Liquid/GHC/Plugin/SpecFinder.hs
377+
[BareSpec]: liquidhaskell-boot/src/Language/Haskell/Liquid/Types/Specs.hs#L362
378+
[LiftedSpec]: liquidhaskell-boot/src/Language/Haskell/Liquid/Types/Specs.hs#L559
379+
[TargetSrc]: liquidhaskell-boot/src/Language/Haskell/Liquid/Types/Specs.hs#L158
380+
[Ghc monad]: https://hackage.haskell.org/package/ghc-9.2.5/docs/GHC.html#t:Ghc
381+
[HscEnv]: https://hackage.haskell.org/package/ghc-9.2.5/docs/GHC.html#t:HscEnv
382+
[DynFlags]: https://hackage.haskell.org/package/ghc-9.2.5/docs/GHC.html#t:DynFlags
383+
[GhcMonad]: https://hackage.haskell.org/package/ghc-9.2.5/docs/GHC.html#t:GhcMonad
384+
[GhcMonadLike]: liquidhaskell-boot/src-ghc/Liquid/GHC/GhcMonadLike.hs
385+
[typechecking phase]: liquidhaskell-boot/src/Language/Haskell/Liquid/GHC/Plugin.hs#L211-L226
378386
[ghcide]: https://github.com/haskell/ghcide
379-
[findRelevantSpecs]: src/Language/Haskell/Liquid/GHC/Plugin/SpecFinder.hs#L61
380-
[core binds]: https://hackage.haskell.org/package/ghc-8.10.1/docs/CoreSyn.html#t:CoreBind
381-
[configureGhcTargets]: src-ghc/Liquid/GHC/Interface.hs#L252
382-
[processTargetModule]: src-ghc/Liquid/GHC/Interface.hs#L481
383-
[processModule]: src/Language/Haskell/Liquid/GHC/Plugin.hs#L393
387+
[findRelevantSpecs]: liquidhaskell-boot/src/Language/Haskell/Liquid/GHC/Plugin/SpecFinder.hs#L65
388+
[core binds]: https://hackage.haskell.org/package/ghc-9.2.5/docs/CoreSyn.html#t:CoreBind
389+
[configureGhcTargets]: liquidhaskell-boot/src-ghc/Liquid/GHC/Interface.hs#L254
390+
[processTargetModule]: liquidhaskell-boot/src-ghc/Liquid/GHC/Interface.hs#L483
391+
[processModule]: liquidhaskell-boot/src/Language/Haskell/Liquid/GHC/Plugin.hs#L509
384392

benchmark-timings/app/Main.hs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,18 +49,18 @@ data Options = Options
4949

5050
options :: Parser Options
5151
options = Options <$>
52-
(many (argument
52+
many (argument
5353
str
5454
(metavar "FILEPATH..."
55-
<> help "The files you wish to process.")))
56-
<*> (many (strOption (long "phase"
55+
<> help "The files you wish to process."))
56+
<*> many (strOption (long "phase"
5757
<> short 'p'
5858
<> metavar "PHASE"
59-
<> help "Phase to include in summary. Can be specified more thance once.")))
60-
<*> (strOption (long "output"
59+
<> help "Phase to include in summary. Can be specified more thance once."))
60+
<*> strOption (long "output"
6161
<> short 'o'
6262
<> metavar "OUTPUTFILEPATH"
63-
<> help "File to which to output CSV contents."))
63+
<> help "File to which to output CSV contents.")
6464

6565
opts :: ParserInfo Options
6666
opts = info (options <**> helper)

cabal.project

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,19 @@ packages: .
1010
./tests
1111
./tests/benchmarks/popl18/lib
1212
./benchmark-timings
13+
./scripts/plot-performance
1314

1415
source-repository-package
1516
type: git
1617
location: https://github.com/qnikst/ghc-timings-report
1718
tag: 45ef3498e35897712bde8e002ce18df6d55f8b15
1819

20+
source-repository-package
21+
type: git
22+
location: https://github.com/timbod7/haskell-chart/
23+
tag: ba85444d3c81774a43b8c2b046084e92869914f4
24+
subdir: chart
25+
1926
allow-newer: ghc-timings:base, rest-rewrite:time
2027

2128
package liquid-fixpoint

scripts/plot-benchmarks/src/Benchmark.hs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ instance Ord Benchmark where
2121
compare lhs rhs = compare (benchTimestamp lhs) (benchTimestamp rhs)
2222

2323
unionAppend :: Map.Map String [Benchmark]
24-
-> Map.Map String Benchmark
25-
-> Map.Map String [Benchmark]
24+
-> Map.Map String Benchmark
25+
-> Map.Map String [Benchmark]
2626
unionAppend l r = Map.unionWith (++) l r'
2727
where
28-
r' = fmap (\a -> [a]) r
28+
r' = (\a -> [a]) <$> r
2929

3030
toBenchMap :: (Foldable f)
3131
=> f Benchmark
@@ -40,8 +40,7 @@ instance FromRecord Benchmark where
4040
<*> pure (error ("Shouldn't be evaluated until after"
4141
++ " reassignment!"))
4242
<*> r .! 1
43-
<*> do asStr <- r .! 2
44-
return $ read asStr {- Since the test suite
43+
<*> (read <$> r .! 2) {- Since the test suite
4544
generates this field by calling show, this read Should Be Safe (TM) -}
4645

4746
csvOutName = "Name"
@@ -51,6 +50,6 @@ csvOutPass = "Success"
5150

5251
instance ToNamedRecord (LocalTime, Benchmark) where
5352
toNamedRecord (_, bm) = namedRecord [csvOutName .= benchName bm,
54-
csvOutDate .= (show $ benchTimestamp bm),
55-
csvOutTime .= (benchTime bm),
56-
csvOutPass .= (show $ benchPass bm)]
53+
csvOutDate .= (show $ benchTimestamp bm),
54+
csvOutTime .= (benchTime bm),
55+
csvOutPass .= (show $ benchPass bm)]

scripts/plot-benchmarks/src/Config.hs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@ module Config where
55
import System.Console.CmdArgs
66
import System.Directory
77

8-
data OutputType =
9-
Svg
10-
| Csv
8+
data OutputType = Svg | Csv
119
deriving (Eq, Data, Typeable, Show)
1210

1311
data Config =
@@ -32,7 +30,7 @@ instance Default Config where
3230
config :: Config
3331
config = Config
3432
{ logDir = pwd &= help "The directory that contains the logs",
35-
outputDir = pwd &= help "The diretory to output graphs to",
33+
outputDir = pwd &= help "The directory to output graphs to",
3634
outputType = Csv &= help "The type of output to produce",
3735
plotCompare = def &= help "Pairs of benchmarks to compare",
3836
plot = def &= help "Benchmarks to plot"

scripts/plot-benchmarks/src/Main.hs

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,13 @@ import Config
55
import Parse
66

77
main :: IO ()
8-
main = do
9-
conf <- getConfig
10-
case (outputType conf) of
11-
Csv -> do
12-
csvData <- getAllData
13-
(logDir conf)
14-
(plot conf)
15-
dumpLogs
16-
(outputDir conf)
17-
csvData
18-
Svg -> do
19-
timeData <- getTimeData
20-
(logDir conf)
21-
(plot conf)
22-
plotTimeData
23-
(outputDir conf)
24-
timeData
25-
compareTimeData <- getCompareTimeData
26-
(logDir conf)
27-
(plotCompare conf)
28-
plotCompareTimeData
29-
(outputDir conf)
30-
compareTimeData
8+
main =
9+
do conf <- getConfig
10+
case outputType conf of
11+
Csv -> do csvData <- getAllData (logDir conf) (plot conf)
12+
dumpLogs (outputDir conf) csvData
13+
Svg -> do timeData <- getTimeData (logDir conf) (plot conf)
14+
plotTimeData (outputDir conf) timeData
15+
compareTimeData <- getCompareTimeData (logDir conf)
16+
(plotCompare conf)
17+
plotCompareTimeData (outputDir conf) compareTimeData

0 commit comments

Comments
 (0)