You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: optimizing/index.md
+29-23Lines changed: 29 additions & 23 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -36,7 +36,7 @@ With this in mind, after you're done with the current page, you should read the
36
36
37
37
## Measurements
38
38
39
-
\tldr{Use BenchmarkTools.jl's `@benchmark` with a setup phase to get the most accurate idea of your code's performance. Use Chairmarks.jl as a faster alternative.}
39
+
\tldr{Use Chairmarks.jl's `@be` with a setup phase to get the most accurate idea of your code's performance.}
40
40
41
41
The simplest way to measure how fast a piece of code runs is to use the `@time` macro, which returns the result of the code and prints the measured runtime and allocations.
42
42
Because code needs to be compiled before it can be run, you should first run a function without timing it so it can be compiled, and then time it:
@@ -53,39 +53,42 @@ using BenchmarkTools
53
53
Using `@time` is quick but it has flaws, because your function is only measured once.
54
54
That measurement might have been influenced by other things going on in your computer at the same time.
55
55
In general, running the same block of code multiple times is a safer measurement method, because it diminishes the probability of only observing an outlier.
56
+
The Chairmarks.jl package provides convenient syntax to do just that.
56
57
57
-
### BenchmarkTools
58
+
### Chairmarks
58
59
59
-
[BenchmarkTools.jl](https://github.com/JuliaCI/BenchmarkTools.jl) is the most popular package for repeated measurements on function executions.
60
-
Similarly to`@time`, BenchmarkTools offers `@btime`which can be used in exactly the same way but will run the code multiple times and provide an average.
61
-
Additionally, by using `$` to [interpolate external values](https://juliaci.github.io/BenchmarkTools.jl/stable/manual/#Interpolating-values-into-benchmark-expressions), you remove the overhead caused by global variables.
60
+
[Chairmarks.jl](https://github.com/LilithHafner/Chairmarks.jl) is the latest benchmarking toolkit, designed to make fast and accurate timing measurements.
61
+
Chairmarks offers`@b` (for "benchmark") which can be used in the same way as `@time`but will run the code multiple times and provide a minimum execution time.
62
+
Alternatively, Chairmarks also provides `@be` to run the same benchmark and output all of its statistics.
62
63
63
-
```>$-example
64
-
using BenchmarkTools
65
-
@btime sum_abs(v);
66
-
@btime sum_abs($v);
64
+
```>chairmarks-example
65
+
using Chairmarks
66
+
@b sum_abs(v)
67
+
@be sum_abs(v)
68
+
```
69
+
70
+
Chairmarks supports a pipeline syntax with optional `init`, `setup`, `teardown`, and `keywords` arguments for more extensive control over the benchmarking process.
71
+
The `sum_abs` function could also be benchmarked using pipeline syntax as below.
72
+
73
+
```>pipeline-example-simple
74
+
@be v sum_abs
67
75
```
68
76
69
-
In more complex settings, you might need to construct variables in a [setup phase](https://juliaci.github.io/BenchmarkTools.jl/stable/manual/#Setup-and-teardown-phases) that is run before each sample.
70
-
This can be useful to generate a new random input every time, instead of always using the same input.
77
+
For a more complicated example, you could write the following to benchmark a matrix multiplication function for one second, excluding the time spent to *setup* the arrays.
71
78
72
-
```>setup-example
79
+
```>pipeline-example-complex
73
80
my_matmul(A, b) = A * b;
74
-
@btime my_matmul(A, b) setup=(
75
-
A = rand(1000, 1000); # use semi-colons between setup lines
For better visualization, the `@benchmark` macro shows performance histograms:
84
+
See the [Chairmarks documentation](https://chairmarks.lilithhafner.com/) for more details on benchmarking options.
85
+
For better visualization, [PrettyChairmarks.jl](https://github.com/astrozot/PrettyChairmarks.jl) shows performance histograms alongside the numerical results.
81
86
82
87
\advanced{
83
-
Certain computations may be [optimized away by the compiler]((https://juliaci.github.io/BenchmarkTools.jl/stable/manual/#Understanding-compiler-optimizations)) before the benchmark takes place.
88
+
No matter the benchmarking tool used, certain computations may be [optimized away by the compiler]((https://juliaci.github.io/BenchmarkTools.jl/stable/manual/#Understanding-compiler-optimizations)) before the benchmark takes place.
84
89
If you observe suspiciously fast performance, especially below the nanosecond scale, this is very likely to have happened.
85
90
}
86
91
87
-
[Chairmarks.jl](https://github.com/LilithHafner/Chairmarks.jl) offers an alternative to BenchmarkTools.jl, promising faster benchmarking while attempting to maintain high accuracy and using an alternative syntax based on pipelines.
88
-
89
92
### Benchmark suites
90
93
91
94
While we previously discussed the importance of documenting breaking changes in packages using [semantic versioning](/sharing/index.md#versions-and-registration), regressions in performance can also be vital to track.
@@ -97,10 +100,13 @@ Several packages exist for this purpose:
97
100
98
101
### Other tools
99
102
100
-
BenchmarkTools.jl works fine for relatively short and simple blocks of code (microbenchmarking).
103
+
Chairmarks.jl works fine for relatively short and simple blocks of code (microbenchmarking).
101
104
To find bottlenecks in a larger program, you should rather use a [profiler](#profiling) or the package [TimerOutputs.jl](https://github.com/KristofferC/TimerOutputs.jl).
102
105
It allows you to label different sections of your code, then time them and display a table of grouped by label.
103
106
107
+
[BenchmarkTools.jl](https://github.com/JuliaCI/BenchmarkTools.jl) is the older standard for benchmarking in Julia. It is still widely used today.
108
+
However, its default parameters run benchmarks for longer than Chairmarks, and it requires interpolating variables into the benchmarked expressions with `$`.
109
+
104
110
Finally, if you know a loop is slow and you'll need to wait for it to be done, you can use [ProgressMeter.jl](https://github.com/timholy/ProgressMeter.jl) or [ProgressLogging.jl](https://github.com/JuliaLogging/ProgressLogging.jl) to track its progress.
105
111
106
112
## Profiling
@@ -141,7 +147,7 @@ To integrate profile visualisations into environments like Jupyter and Pluto, us
141
147
No matter which tool you use, if your code is too fast to collect samples, you may need to run it multiple times in a loop.
142
148
143
149
\advanced{
144
-
To visualize memory allocation profiles, use PProf.jl or VSCode's `@profview_allocs`.
150
+
To visualize memory allocation profiles, use PProf.jl or VSCode's `@profview_allocs`.
145
151
A known issue with the allocation profiler is that it is not able to determine the type of every object allocated, instead `Profile.Allocs.UnknownType` is shown instead.
146
152
Inspecting the call graph can help identify which types are responsible for the allocations.
147
153
}
@@ -386,7 +392,7 @@ However, in order for all workers to know about a function or module, we have to
386
392
using Distributed
387
393
388
394
# Add additional workers then load code on the workers
0 commit comments