Benchmarking

This notebook shows some @benchmark and @code_warntype output. Both outputs are shown via the with_terminal from PlutoUI.jl, see below.

We define some function double and a dictionary of numbers in order to show type inference problems via @code_warntype:

numbers = Dict(:one => 1f0, :two => 2.0)
Dict{Symbol, AbstractFloat} with 2 entries:
  :two => 2.0
  :one => 1.0
function double(mapping, key::Symbol)
    return 2 * mapping[key]
end;

Now, the code works.

double(numbers, :one)
2.0f0
double(numbers, :two)
4.0

But the @code_warntype shows some big red warnings:

using PlutoUI: with_terminal
with_terminal() do
    @code_warntype double(numbers, :one)
end
MethodInstance for Main.var\"workspace#4\".double(::Dict{Symbol, AbstractFloat}, ::Symbol)
  from double(�[90mmapping�[39m, �[90mkey�[39m::�[1mSymbol�[22m)�[90m @�[39m �[90mMain.var\"workspace#4\"�[39m �[90m~/work/JuliaTutorialsTemplate/JuliaTutorialsTemplate/tutorials/�[39m�[90m�[4mbenchmarking.jl#==#3f0e2049-8597-4dac-b499-4d7a8a35978e:1�[24m�[39m
Arguments
  #self#�[36m::Core.Const(Main.var\"workspace#4\".double)�[39m
  mapping�[36m::Dict{Symbol, AbstractFloat}�[39m
  key�[36m::Symbol�[39m
Body�[91m�[1m::Any�[22m�[39m
�[90m1 ─�[39m %1 = Base.getindex(mapping, key)�[91m�[1m::AbstractFloat�[22m�[39m
�[90m│  �[39m %2 = (2 * %1)�[91m�[1m::Any�[22m�[39m
�[90m└──�[39m      return %2

We can fix this by forcing all elements in the dictionary to have the same type. Specifically, to we force all elements to be of type Float64:

typednumbers = Dict{Symbol, Float64}(:one => 1f0, :two => 2.0)
Dict{Symbol, Float64} with 2 entries:
  :two => 2.0
  :one => 1.0

This gets rid of all the type warnings:

with_terminal() do
    @code_warntype double(typednumbers, :one)
end
MethodInstance for Main.var\"workspace#4\".double(::Dict{Symbol, Float64}, ::Symbol)
  from double(�[90mmapping�[39m, �[90mkey�[39m::�[1mSymbol�[22m)�[90m @�[39m �[90mMain.var\"workspace#4\"�[39m �[90m~/work/JuliaTutorialsTemplate/JuliaTutorialsTemplate/tutorials/�[39m�[90m�[4mbenchmarking.jl#==#3f0e2049-8597-4dac-b499-4d7a8a35978e:1�[24m�[39m
Arguments
  #self#�[36m::Core.Const(Main.var\"workspace#4\".double)�[39m
  mapping�[36m::Dict{Symbol, Float64}�[39m
  key�[36m::Symbol�[39m
Body�[36m::Float64�[39m
�[90m1 ─�[39m %1 = Base.getindex(mapping, key)�[36m::Float64�[39m
�[90m│  �[39m %2 = (2 * %1)�[36m::Float64�[39m
�[90m└──�[39m      return %2

And makes the method more quick:

using BenchmarkTools
with_benchmark_terminal() do
    @benchmark double(numbers, :one)
end
BenchmarkTools.Trial: 10000 samples with 990 evaluations.
 Range (min … max):  40.303 ns …  3.804 μs  ┊ GC (min … max): 0.00% … 97.73%
 Time  (median):     50.910 ns              ┊ GC (median):    0.00%
 Time  (mean ± σ):   58.816 ns ± 58.810 ns  ┊ GC (mean ± σ):  1.21% ±  1.38%

    ▃▇█▅                                                       
  ▂▃████▇██▇▄▅▄▄▄▄▃▃▃▃▃▂▃▃▃▃▃▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▁▂▂▂▂▂ ▃
  40.3 ns         Histogram: frequency by time         141 ns <

 Memory estimate: 16 bytes, allocs estimate: 1.
with_benchmark_terminal() do
    @benchmark double(typednumbers, :one)
end
BenchmarkTools.Trial: 10000 samples with 996 evaluations.
 Range (min … max):  22.289 ns …  21.118 μs  ┊ GC (min … max): 0.00% … 0.00%
 Time  (median):     27.108 ns               ┊ GC (median):    0.00%
 Time  (mean ± σ):   70.159 ns ± 670.966 ns  ┊ GC (mean ± σ):  4.03% ± 1.71%

  ▅▇█▅▅▄▃▅▆▅▃▃▃▃▃▃▂▁▁▁▁▁                                       ▂
  ████████████████████████▇▇▇██▇▇▇▇▇▇▇▆▅▅▅▅▅▃▅▅▃▅▄▃▄▄▂▄▃▃▂▄▄▅▄ █
  22.3 ns       Histogram: log(frequency) by time       104 ns <

 Memory estimate: 16 bytes, allocs estimate: 1.

Appendix

function with_benchmark_terminal(f)
    out = sprint(show, "text/plain", f())
    with_terminal() do
        print(out)
    end
end;

Built with Julia 1.9.1 and

BenchmarkTools 1.3.2
PlutoUI 0.7.51

To run this tutorial locally, download this file and open it with Pluto.jl.