Call overhead of keyword args

I was reading
https://docs.julialang.org/en/v1/manual/performance-tips/index.html#Declare-types-of-keyword-arguments-1

I could not really follow what is said there (“Functions with keyword arguments have near-zero overhead for call sites that pass only positional arguments.”) Is there a call overhead to a simple
f(x, val = y) compared to f(x,y)?

A small experiment suggest not:

f(x) = x+1

g(f, x, n) = let y = x; for i in 1:n; y = f(y); end; y end

f2(x;y=x) = f(y)
g2(f2, x, n) = let y = x; for i in 1:n; y = f2(y; y=y); end; y end
julia> @btime g(f, 1, 10_000)
  5.091 ns (0 allocations: 0 bytes)
10001

julia> @btime g2(f2, 1, 10_000)
  5.096 ns (0 allocations: 0 bytes)
10001

Or is this maybe to simple to trigger a problem.

I think that section is no longer relevant, since it stems from a time when keyword arguments were indeed slower because they were not yet implemented using NamedTuples (https://github.com/JuliaLang/julia/pull/24795). See https://github.com/JuliaLang/julia/pull/24987 for the proposed removal of that section.

3 Likes

I’ve seen this so many times now on this forum – Please whenever you get timings in the low nanoseconds, be very suspicious! A 3 GHz CPU executes 3 clock cycles in 1 ns, so 5 ns means ~15 clock cycles, which is not a lot of time, and obviously not enough to iterate 10,000 times. It most likely means that either the compiler is clever enough to eliminate/pre-calculate the for loop, or the expression executes too quickly for the timing to work correctly.

3 Likes