Skip to content

Commit

Permalink
More readable result tables in markdown (#60)
Browse files Browse the repository at this point in the history
The result tables are written to markdown with aligned columns, so that
the resulting file is human-readable without having to convert it to
html.

This commit also implements the missing method
`export_markdown(::String, ::BenchmarkJudgement)` that allows to write
the result of `judge` directly to a file.
  • Loading branch information
goerz authored and KristofferC committed Feb 12, 2018
1 parent 3854dd2 commit 0ee84db
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 18 deletions.
22 changes: 16 additions & 6 deletions src/benchmarkjudgement.jl
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ function Base.show(io::IO, judgement::BenchmarkJudgement)
base.julia_commit[1:6])
end

function export_markdown(file::String, results::BenchmarkJudgement)
open(file, "w") do f
export_markdown(f, results)
end
end

function export_markdown(io::IO, judgement::BenchmarkJudgement)
target, baseline = judgement.target_results, judgement.baseline_results
Expand Down Expand Up @@ -77,23 +82,28 @@ function export_markdown(io::IO, judgement::BenchmarkJudgement)
- Baseline: $(env_strs(baseline))
""")

entries = BenchmarkTools.leaves(benchmarkgroup(judgement))
entries = entries[sortperm(map(x -> string(first(x)), entries))]

cw = [2, 10, 12]
for (ids, t) in entries
_update_col_widths!(cw, ids, t)
end

print(io, """
## Results
A ratio greater than `1.0` denotes a possible regression (marked with $(_REGRESS_MARK)), while a ratio less
than `1.0` denotes a possible improvement (marked with $(_IMPROVE_MARK)). Only significant results - results
that indicate possible regressions or improvements - are shown below (thus, an empty table means that all
benchmark results remained invariant between builds).
| ID | time ratio | memory ratio |
|----|------------|--------------|
| ID$(" "^(cw[1]-2)) | time ratio$(" "^(cw[2]-10)) | memory ratio$(" "^(cw[3]-12)) |
|---$("-"^(cw[1]-2))-|-----------$("-"^(cw[2]-10))-|-------------$("-"^(cw[3]-12))-|
""")

entries = BenchmarkTools.leaves(benchmarkgroup(judgement))
entries = entries[sortperm(map(x -> string(first(x)), entries))]

for (ids, t) in entries
if BenchmarkTools.isregression(t) || BenchmarkTools.isimprovement(t)
println(io, _resultrow(ids, t))
println(io, _resultrow(ids, t, cw))
end
end

Expand Down
17 changes: 11 additions & 6 deletions src/benchmarkresults.jl
Original file line number Diff line number Diff line change
Expand Up @@ -134,17 +134,22 @@ function export_markdown(io::IO, results::BenchmarkResults)
An empty cell means that the value was zero.
""")

print(io, """
| ID | time | GC time | memory | allocations |
|----|-----:|--------:|-------:|------------:|
""")

entries = BenchmarkTools.leaves(benchmarkgroup(results))
entries = entries[sortperm(map(x -> string(first(x)), entries))]

cw = [2, 4, 7, 6, 11]
for (ids, t) in entries
_update_col_widths!(cw, ids, t)
end

print(io, """
| ID$(" "^(cw[1]-2)) | time$(" "^(cw[2]-4)) | GC time$(" "^(cw[3]-7)) | memory$(" "^(cw[4]-6)) | allocations$(" "^(cw[5]-11)) |
|---$("-"^(cw[1]-2))-|-----$("-"^(cw[2]-4)):|--------$("-"^(cw[3]-7)):|-------$("-"^(cw[4]-6)):|------------$("-"^(cw[5]-11)):|
""")


for (ids, t) in entries
println(io, _resultrow(ids, t))
println(io, _resultrow(ids, t, cw))
end
println(io)
println(io, """
Expand Down
49 changes: 43 additions & 6 deletions src/util.jl
Original file line number Diff line number Diff line change
Expand Up @@ -60,20 +60,40 @@ _benchwarn(str) = print_with_color(Base.info_color(), STDOUT, "PkgBenchmark: ",

_idrepr(id) = (str = repr(id); str[searchindex(str, '['):end])
_intpercent(p) = string(ceil(Int, p * 100), "%")
_resultrow(ids, t::BenchmarkTools.Trial) = _resultrow(ids, minimum(t))
_resultrow(ids, t::BenchmarkTools.Trial, col_widths) =
_resultrow(ids, minimum(t), col_widths)

function _resultrow(ids, t::BenchmarkTools.TrialEstimate)
_update_col_widths!(col_widths, ids, t::BenchmarkTools.Trial) =
_update_col_widths!(col_widths, ids, minimum(t))


function _resultrow(ids, t::BenchmarkTools.TrialEstimate, col_widths)
t_tol = _intpercent(BenchmarkTools.params(t).time_tolerance)
m_tol = _intpercent(BenchmarkTools.params(t).memory_tolerance)
timestr = BenchmarkTools.time(t) == 0 ? "" : string(BenchmarkTools.prettytime(BenchmarkTools.time(t)), " (", t_tol, ")")
memstr = BenchmarkTools.memory(t) == 0 ? "" : string(BenchmarkTools.prettymemory(BenchmarkTools.memory(t)), " (", m_tol, ")")
gcstr = BenchmarkTools.gctime(t) == 0 ? "" : BenchmarkTools.prettytime(BenchmarkTools.gctime(t))
allocstr = BenchmarkTools.allocs(t) == 0 ? "" : string(BenchmarkTools.allocs(t))
return "| $(rpad("`"*_idrepr(ids)*"`", col_widths[1])) | $(lpad(timestr, col_widths[2])) | $(lpad(gcstr, col_widths[3])) | $(lpad(memstr, col_widths[4])) | $(lpad(allocstr, col_widths[5])) |"
end


function _update_col_widths!(col_widths, ids, t::BenchmarkTools.TrialEstimate)
t_tol = _intpercent(BenchmarkTools.params(t).time_tolerance)
m_tol = _intpercent(BenchmarkTools.params(t).memory_tolerance)
timestr = BenchmarkTools.time(t) == 0 ? "" : string(BenchmarkTools.prettytime(BenchmarkTools.time(t)), " (", t_tol, ")")
memstr = BenchmarkTools.memory(t) == 0 ? "" : string(BenchmarkTools.prettymemory(BenchmarkTools.memory(t)), " (", m_tol, ")")
gcstr = BenchmarkTools.gctime(t) == 0 ? "" : BenchmarkTools.prettytime(BenchmarkTools.gctime(t))
allocstr = BenchmarkTools.allocs(t) == 0 ? "" : string(BenchmarkTools.allocs(t))
return "| `$(_idrepr(ids))` | $(timestr) | $(gcstr) | $(memstr) | $(allocstr) |"
idrepr = "`"*_idrepr(ids)*"`"
for (i, s) in enumerate((idrepr, timestr, gcstr, memstr, allocstr))
w = length(s)
if (w > col_widths[i]) col_widths[i] = w end
end
end


function _resultrow(ids, t::BenchmarkTools.TrialJudgement)
function _resultrow(ids, t::BenchmarkTools.TrialJudgement, col_widths)
t_tol = _intpercent(BenchmarkTools.params(t).time_tolerance)
m_tol = _intpercent(BenchmarkTools.params(t).memory_tolerance)
t_ratio = @sprintf("%.2f", BenchmarkTools.time(BenchmarkTools.ratio(t)))
Expand All @@ -82,10 +102,27 @@ function _resultrow(ids, t::BenchmarkTools.TrialJudgement)
m_mark = _resultmark(BenchmarkTools.memory(t))
timestr = "$(t_ratio) ($(t_tol)) $(t_mark)"
memstr = "$(m_ratio) ($(m_tol)) $(m_mark)"
return "| `$(_idrepr(ids))` | $(timestr) | $(memstr) |"
return "| $(rpad("`"*_idrepr(ids)*"`", col_widths[1])) | $(lpad(timestr, col_widths[2])) | $(lpad(memstr, col_widths[3])) |"
end


function _update_col_widths!(col_widths, ids, t::BenchmarkTools.TrialJudgement)
t_tol = _intpercent(BenchmarkTools.params(t).time_tolerance)
m_tol = _intpercent(BenchmarkTools.params(t).memory_tolerance)
t_ratio = @sprintf("%.2f", BenchmarkTools.time(BenchmarkTools.ratio(t)))
m_ratio = @sprintf("%.2f", BenchmarkTools.memory(BenchmarkTools.ratio(t)))
t_mark = _resultmark(BenchmarkTools.time(t))
m_mark = _resultmark(BenchmarkTools.memory(t))
timestr = "$(t_ratio) ($(t_tol)) $(t_mark)"
memstr = "$(m_ratio) ($(m_tol)) $(m_mark)"
idrepr = "`"*_idrepr(ids)*"`"
for (i, s) in enumerate((idrepr, timestr, memstr))
w = length(s)
if (w > col_widths[i]) col_widths[i] = w end
end
end

_resultmark(sym::Symbol) = sym == :regression ? _REGRESS_MARK : (sym == :improvement ? _IMPROVE_MARK : "")

const _REGRESS_MARK = ":x:"
const _IMPROVE_MARK = ":white_check_mark:"
const _IMPROVE_MARK = ":white_check_mark:"

0 comments on commit 0ee84db

Please sign in to comment.