Anonymous functions slower than proper functions?

Is this expected behavior? I see a performance difference of a factor two for very simple functions. E.g.:

using BenchmarkTools

g1 = t -> cos(t - 0.5 * t^2)
g2(t) = cos(t - 0.5 * t^2)

function h1()
    x = 0.
    for i in 1.:10000.
        x += g1(i)
    end
    x
end

function h2()
    x = 0.
    for i in 1.:10000.
        x += g2(i)
    end
    x
end

b3 = @benchmark h1()
b4 = @benchmark h2()

printstyled("Anonymous function:\n\n"; bold=true)
display(b3) # min 745.989 μs

printstyled("One line function:\n\n"; bold=true)
display(b4) # min 402.577 μs

Came up because DiffEq has anonymous functions in the Documentation here:

https://diffeq.sciml.ai/stable/tutorials/ode_example/#Example-3:-Solving-Nonhomogeneous-Equations-using-Parameterized-Functions

At a very quick glance I didn’t see any warnings about anonymous functions and performance anywhere either.

The problem is that g1 is a non-constant global, if you use

const g1 = t -> cos(t - 0.5 * t^2)

the performance should be the same. (or if you put everything inside a function, making g1 local to the function scope).

2 Likes

Thank you. I completely missed that. And this was on top of a refactor where I removed globals as well.

So this doesn’t actually make a difference if I pass the global to another function, e.g. a solver from DiffEq:


using BenchmarkTools

g1 = t -> cos(t - 0.5 * t^2)
g2(t) = cos(t - 0.5 * t^2)

function h(g)
    x = 0.
    for i in 1.:10000.
        x += g(i)
    end
    x
end


b3 = @benchmark h($g1)
b4 = @benchmark h($g2)

printstyled("Anonymous function:\n\n"; bold=true)
display(b3) # min 402.685 μs

printstyled("One line function:\n\n"; bold=true)
display(b4) # min 402.083 μs