Skip to content

Commit 6008719

Browse files
committed
Add some rudimentary documentation
1 parent 05d971f commit 6008719

File tree

1 file changed

+70
-1
lines changed

1 file changed

+70
-1
lines changed

docs/src/manual.md

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,18 @@ You can pass the following keyword arguments to `@benchmark`, `@benchmarkable`,
8686
- `time_tolerance`: The noise tolerance for the benchmark's time estimate, as a percentage. This is utilized after benchmark execution, when analyzing results. Defaults to `BenchmarkTools.DEFAULT_PARAMETERS.time_tolerance = 0.05`.
8787
- `memory_tolerance`: The noise tolerance for the benchmark's memory estimate, as a percentage. This is utilized after benchmark execution, when analyzing results. Defaults to `BenchmarkTools.DEFAULT_PARAMETERS.memory_tolerance = 0.01`.
8888

89-
To change the default values of the above fields, one can mutate the fields of `BenchmarkTools.DEFAULT_PARAMETERS`, for example:
89+
The following keyword arguments relate to [Running custom benchmarks] are experimental and subject to change, see [Running custom benchmarks] for furthe details.:
90+
91+
- `run_customizable_func_only`: If `true`, only the customizable benchmark. Defaults to `BenchmarkTools.DEFAULT_PARAMETERS..run_customizable_func_only = false`.
92+
- `enable_customizable_func`: If `:ALL` the customizable benchmark runs on every sample, if `:LAST` the customizable benchmark runs on the last sample, if `:FALSE` the customizable benchmark is never run. Defaults to `BenchmarkTools.DEFAULT_PARAMETERS.enable_customizable_func = :FALSE`
93+
- `customizable_gcsample`: If `true`, runs `gc()` before each sample of the customizable benchmark. Defaults to `BenchmarkTools.DEFAULT_PARAMETERS.customizable_gcsample = false`
94+
- `setup_prehook`: Defaults to `BenchmarkTools.DEFAULT_PARAMETERS.teardown_posthook = _nothing_func`, which returns nothing.
95+
- `teardown_posthook`: Defaults to `BenchmarkTools.DEFAULT_PARAMETERS.teardown_posthook = _nothing_func`, which returns nothing.
96+
- `sample_result`: Defaults to `BenchmarkTools.DEFAULT_PARAMETERS.teardown_posthook = _nothing_func`, which returns nothing.
97+
- `prehook`: Defaults to `BenchmarkTools.DEFAULT_PARAMETERS.teardown_posthook = _nothing_func`, which returns nothing.
98+
- `posthook`: Defaults to `BenchmarkTools.DEFAULT_PARAMETERS.teardown_posthook = _nothing_func`, which returns nothing.
99+
100+
To change the default values of the above fields, one can mutate the fields of `BenchmarkTools.DEFAULT_PARAMETERS` (this is not supported for `prehook` and `posthook`), for example:
90101

91102
```julia
92103
# change default for `seconds` to 2.5
@@ -347,10 +358,20 @@ BenchmarkTools.Trial
347358
gcsample: Bool false
348359
time_tolerance: Float64 0.05
349360
memory_tolerance: Float64 0.01
361+
run_customizable_func_only: Bool false
362+
enable_customizable_func: Symbol FALSE
363+
customizable_gcsample: Bool false
364+
setup_prehook: _nothing_func (function of type typeof(BenchmarkTools._nothing_func))
365+
teardown_posthook: _nothing_func (function of type typeof(BenchmarkTools._nothing_func))
366+
sample_result: _nothing_func (function of type typeof(BenchmarkTools._nothing_func))
367+
prehook: _nothing_func (function of type typeof(BenchmarkTools._nothing_func))
368+
posthook: _nothing_func (function of type typeof(BenchmarkTools._nothing_func))
350369
times: Array{Float64}((10000,)) [26549.0, 26960.0, 27030.0, 27171.0, 27211.0, 27261.0, 27270.0, 27311.0, 27311.0, 27321.0 55383.0, 55934.0, 58649.0, 62847.0, 68547.0, 75761.0, 247081.0, 1.421718e6, 1.488322e6, 1.50329e6]
351370
gctimes: Array{Float64}((10000,)) [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.366184e6, 1.389518e6, 1.40116e6]
352371
memory: Int64 16752
353372
allocs: Int64 19
373+
customizable_result: Nothing nothing
374+
customizable_result_for_every_sample: Bool false
354375
```
355376

356377
As you can see from the above, a couple of different timing estimates are pretty-printed with the `Trial`. You can calculate these estimates yourself using the `minimum`, `maximum`, `median`, `mean`, and `std` functions (Note that `median`, `mean`, and `std` are reexported in `BenchmarkTools` from `Statistics`):
@@ -1008,3 +1029,51 @@ This will display each `Trial` as a violin plot.
10081029
- BenchmarkTools attempts to be robust against machine noise occurring between *samples*, but BenchmarkTools can't do very much about machine noise occurring between *trials*. To cut down on the latter kind of noise, it is advised that you dedicate CPUs and memory to the benchmarking Julia process by using a shielding tool such as [cset](http://manpages.ubuntu.com/manpages/precise/man1/cset.1.html).
10091030
- On some machines, for some versions of BLAS and Julia, the number of BLAS worker threads can exceed the number of available cores. This can occasionally result in scheduling issues and inconsistent performance for BLAS-heavy benchmarks. To fix this issue, you can use `BLAS.set_num_threads(i::Int)` in the Julia REPL to ensure that the number of BLAS threads is equal to or less than the number of available cores.
10101031
- `@benchmark` is evaluated in global scope, even if called from local scope.
1032+
1033+
## Experimental - Running custom benchmarks
1034+
1035+
If you want to run code during a benchmark, e.g. to collect different metrics, say using perf, you can configure a custom benchmark.
1036+
A custom benchmark runs in the following way, where `benchmark_function` is the function we are benchmarking:
1037+
```julia
1038+
local setup_prehook_result
1039+
try
1040+
setup_prehook_result = setup_prehook(params)
1041+
$(setup)
1042+
prehook_result = prehook()
1043+
for _ in 1:evals
1044+
benchmark_function()
1045+
end
1046+
posthook_result = posthook()
1047+
return sample_result(params, setup_prehook_result, prehook_result, posthook_result)
1048+
finally
1049+
$(teardown)
1050+
teardown_posthook(params, setup_prehook_result)
1051+
end
1052+
```
1053+
The result from `sample_result` is collected and can be accessed from the `customizable_result` field of `Trial`, which is the type of a benchmark result.
1054+
1055+
Note that `prehook` and `posthook` should be as simple and fast as possible, moving any heavy lifting to `setup_prehook`, `sample_result` and `teardown_posthook`.
1056+
1057+
As an example, these are the hooks to replicate the normal benchmarking functionality
1058+
```julia
1059+
setup_prehook(_) = nothing
1060+
samplefunc_prehook() = (Base.gc_num(), time_ns())
1061+
samplefunc_posthook = samplefunc_prehook
1062+
function samplefunc_sample_result(params, _, prehook_result, posthook_result)
1063+
evals = params.evals
1064+
sample_time = posthook_result[2] - prehook_result[2]
1065+
gcdiff = Base.GC_Diff(posthook_result[1], prehook_result[1])
1066+
1067+
time = max((sample_time / evals) - params.overhead, 0.001)
1068+
gctime = max((gcdiff.total_time / evals) - params.overhead, 0.0)
1069+
memory = Int(Base.fld(gcdiff.allocd, evals))
1070+
allocs = Int(
1071+
Base.fld(
1072+
gcdiff.malloc + gcdiff.realloc + gcdiff.poolalloc + gcdiff.bigalloc,
1073+
evals,
1074+
),
1075+
)
1076+
return time, gctime, memory, allocs
1077+
end
1078+
teardown_posthook(_, _) = nothing
1079+
```

0 commit comments

Comments
 (0)