PkgJogger.jl is a Revise-compatible, boilerplate-free tool for running your package’s benchmarking suite built on top of BenchmarkTools.jl. I’ve been using it for about a year and figured it was time to share it with the community.
Just Write Benchmarks
Throw your benchmarks into a file named benchmark/bench_*.jl
, define a suite
, and you’re off to the races with @jog PkgName
. PkgJogger will wrap each file into a separate module (Think SafeTestsets) and create a module (JogPkgName) for running, saving, loading, and judging your benchmarks.
using BenchmarkTools
using AwesomePkg
suite = BenchmarkGroup()
suite["fast"] = @benchmarkable fast_code()
using AwesomePkg
using PkgJogger
# Creates the JogAwesomePkg module
@jog AwesomePkg
# Warmup, tune, run and save all of AwesomePkg's benchmarks
julia> JogAwesomePkg.benchmark(; save=true)
[ Info: Saved results to .../benchmark/trial/a86f6b29-1bd6-4a9d-b902-c98daf293858.bson.gz
1-element BenchmarkTools.BenchmarkGroup:
tags: []
"bench_code.jl" => 2-element BenchmarkTools.BenchmarkGroup:
tags: []
"fast" => Trial(1.160 ms)
Results are saved to compressed BSON files in PKG_ROOT/benchmark/trial/UUID.bson.gz
, and take roughly ~1/7th the space of *.json
files created by BenchmarkTools.save
. Plus they contain various metadata: git status, system info, Julia version, and PkgJogger version.
Benchmark, Revise, and Benchmark Again!
Code not quite as fast as you’d like? PkgJogger works with Revise.jl; so whether you forgot to escape a pesky variable or want to tweak your code, PkgJogger will be ready to run the latest version on the next JogAwesomePkg.benchmark()
For example, I edited my package’s code, re-ran the benchmarks, and then used JogAwesomePkg.judge
to compare the results. Like most things in PkgJogger, the heavy lifting is performed by BenchmarkTools.jl.
julia> JogAwesomePkg.benchmark(; save=true)
[ Info: Saved results to /Users/alexwadell/.julia/dev/PkgJogger/test/Example.jl/benchmark/trial/c9a0f1c2-d54b-4094-acf8-eb3912f86937.bson.gz
1-element BenchmarkTools.BenchmarkGroup:
tags: []
"bench_code.jl" => 2-element BenchmarkTools.BenchmarkGroup:
tags: []
"fast" => Trial(3.208 ms)
julia> JogAwesomePkg.judge("c9a0f1c2-d54b-4094-acf8-eb3912f86937", "a86f6b29-1bd6-4a9d-b902-c98daf293858")
1-element BenchmarkTools.BenchmarkGroup:
tags: []
"bench_code.jl" => 2-element BenchmarkTools.BenchmarkGroup:
tags: []
"fast" => TrialJudgement(+98.58% => regression)
Long Tuning Times?
Like to benchmark but hate waiting for tuning? PkgJogger can reuse the tune from a prior run to partially or entirely skip the tunning step.
julia> JogAwesomePkg.benchmark(; ref="c9a0f1c2-d54b-4094-acf8-eb3912f86937")
Continuous benchmarking Backed In!
Do you want to run your benchmarks as part of your CI? PkgJogger’s got you. JogAwesomPkg.ci()
will instantiate a benchmarking project (benchmark/Project.toml
), run the suite, and save your results with a one-liner:
julia -e 'using Pkg; Pkg.add("PkgJogger"); using PkgJogger; PkgJogger.ci()
Or, if you use GitHub actions, just add uses: awadell1/PkgJogger.jl@latest
to your workflow.
Smoke out Broken Benchmarks
Ever write benchmarks ages ago only to find they no longer work with the current code? @test_benchmarks AwesomePkg
will run each benchmark once and make sure they don’t error out. While not a perfect test, @test_benchmarks
can serve as a quick smoke test of the benchmarking suite.
julia> using AwesomePkg, PkgJogger
julia> @test_benchmarks AwesomePkg
Test Summary: | Pass Total
bench_code.jl | 1 1
[...]
Plays Nice with Others
Sometimes it’s nice to use BenchmarkTools.jl directly, and skip the PkgJogger workflow. PkgJogger doesn’t add any code to your benchmark/bench_*.jl
files, so just include
the file (Or includet
to use Revise.jl) and use BenchmarkTools.jl to run the suite
directly.
Missing some features provided by PkgBenchmarks.jl or BenchmarkCI.jl? PkgJogger can populate the benchmark/benchmarks.jl
file for you:
using AwesomePkg
using PkgJogger
@jog AwesomePkg
const SUITE = JogAwesomePkg.suite()