From b7190684a683b9457d5e69fc2130a7970654b227 Mon Sep 17 00:00:00 2001 From: David Gustavsson Date: Sun, 18 Jun 2023 19:32:49 +0200 Subject: [PATCH] Plot numeric-keyed groups --- BenchmarkPlots/src/BenchmarkPlots.jl | 31 ++++++++++++++------ docs/generate_plots.jl | 28 ++++++++++++++++++ docs/src/assets/algorithms.png | Bin 0 -> 29264 bytes docs/src/assets/violins.png | Bin 0 -> 13295 bytes docs/src/manual.md | 41 ++++++++++++++++++++++++--- 5 files changed, 88 insertions(+), 12 deletions(-) create mode 100644 docs/generate_plots.jl create mode 100644 docs/src/assets/algorithms.png create mode 100644 docs/src/assets/violins.png diff --git a/BenchmarkPlots/src/BenchmarkPlots.jl b/BenchmarkPlots/src/BenchmarkPlots.jl index 54f26b4f..2d00c715 100644 --- a/BenchmarkPlots/src/BenchmarkPlots.jl +++ b/BenchmarkPlots/src/BenchmarkPlots.jl @@ -1,6 +1,6 @@ module BenchmarkPlots using RecipesBase -using BenchmarkTools: Trial, BenchmarkGroup +using BenchmarkTools: Trial, BenchmarkGroup, mean @recipe function f(::Type{Trial}, t::Trial) seriestype --> :violin @@ -10,16 +10,31 @@ using BenchmarkTools: Trial, BenchmarkGroup t.times end -@recipe function f(g::BenchmarkGroup, keys=keys(g)) - legend --> false +@recipe function f(g::BenchmarkGroup, keyset=keys(g)) yguide --> "t / ns" - for k in keys - @series begin - label --> string(k) - xticks --> true - [string(k)], g[k] + if all(isa.(keyset, Number)) + keyvec = sort([keyset...]) + fillrange := [mean(g[key]).time for key in keyvec] + seriestype --> :path + fillalpha --> 0.5 + keyvec, [minimum(g[key]).time for key in keyvec] + else + legend --> false + for key in keyset + @series begin + label --> string(key) + xticks --> true + [string(key)], g[key] + end end end end +# If a BenchmarkGroup has BenchmarkGroups for elements, ignore the xtick string given by +# parent, just run BenchmarkGroup recipe again +@recipe function f(::AbstractVector{String}, g::BenchmarkGroup) + legend --> true + return g +end + end diff --git a/docs/generate_plots.jl b/docs/generate_plots.jl new file mode 100644 index 00000000..21a05e72 --- /dev/null +++ b/docs/generate_plots.jl @@ -0,0 +1,28 @@ +using BenchmarkTools, Plots, BenchmarkPlots, StatsPlots + +function runalgorithm(x, alg) + alg == :default && return sort(x) + alg == :insertion && return sort(x; alg=InsertionSort) + alg == :quick && return sort(x; alg=QuickSort) + alg == :merge && return sort(x; alg=MergeSort) +end + +g = BenchmarkGroup() +for key in [:default, :insertion, :quick, :merge] + g[key] = @benchmarkable runalgorithm(x, $key) setup=(x=randn(1000)) +end +res = run(g) +plot(res; yscale=:log10) +savefig("$(pkgdir(BenchmarkTools))/docs/src/assets/violins.png") + +g = BenchmarkGroup() +for key in [:default, :insertion, :quick, :merge] + g[key] = BenchmarkGroup() + for size in 2 .^ (1:15) + g[key][size] = @benchmarkable runalgorithm(x, $key) setup=(x=randn($size)) + end +end +res = run(g) +plot(res; scale=:log10, xguide=:size, legendposition=:topleft) +savefig("$(pkgdir(BenchmarkTools))/docs/src/assets/algorithms.png") + diff --git a/docs/src/assets/algorithms.png b/docs/src/assets/algorithms.png new file mode 100644 index 0000000000000000000000000000000000000000..ca6d9c4b106af66c1ce331521fa25e1e4b120114 GIT binary patch literal 29264 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 literal 0 HcmV?d00001 diff --git a/docs/src/manual.md b/docs/src/manual.md index d0c732b0..188e7c69 100644 --- a/docs/src/manual.md +++ b/docs/src/manual.md @@ -974,19 +974,52 @@ plot(t) ``` This will show the timing results of the trial as a violin plot. You can use -all the keyword arguments from `Plots.jl`, for instance `st=:box` or -`yaxis=:log10`. +all the keyword arguments from `Plots.jl`, for instance `seriestype=:box` or +`yscale=:log10`. If a `BenchmarkGroup` contains (only) `Trial`s, its results can be visualized simply by ```julia using BenchmarkPlots, StatsPlots +g = BenchmarkGroup() +for alg in algorithm_symbols + g[alg] = @benchmarkable runalgorithm(x, $alg) setup=(x=randn(1000)) +end t = run(g) -plot(t) +plot(t; yscale=:log10) +``` + +This will display each `Trial` as a violin plot. + +![Violin plots of BenchmarkGroup](./assets/violins.png) + +A `BenchmarkGroup` whose +elements are `BenchmarkGroup`s can be visualized the same way, but no separation +will be made between the element groups - shared keys will get several violins, +and there is no visual indication that a result belongs to one group or the +other. + +The exception is `BenchmarkGroup`s whose keys are `Number`s. These keys will be +interpreted as a size parameter, and the violin plots will be replaced by a line +plot showing the minimum time, with a shaded region up to the mean time. If you +want to bypass this, to still get violin (or similar) plots for the numeric +keys, explicitly make them strings. + +```julia +g = BenchmarkGroup() +for alg in algorithm_symbols + g[alg] = BenchmarkGroup() + for size in 2 .^ [1:15] + g[alg][size] = @benchmarkable runalgorithm(x, $alg) +setup=(x=randn($size)) + end +end +t = run(g) +plot(t; scale=:log10, xguide="size", legendposition=:topleft) ``` -This will display each `Trial` as a violin plot. +![Plot of a BenchmarkGroup containing BenchmarkGroups with numerical keys](./assets/algorithms.png) ## Miscellaneous tips and info