Weird allocations

I was working some numeric integration stuff when I encountered a lot of small allocations for which I couldn’t find a source for.

Here is a MWE demonstrating the behaviour

function f1(f, x)
    s = 0.0
    for i in 1:2
        s += f(x)
    end
    s
end
function f2(f, x)
    s = 0.0
    for j in 1:100
        s += f1(f, x)
    end
    s
end

g(x) = @fastmath sqrt(x)
@time f1(g, 1.0)
# no allocations

@time f2(g, 1.0)
# 300 allocations, 4800 bytes

@noinline g2(x) = x
@time f2(g2, 1.0)
# no allocations

Looking at @code_native didn’t give any reason to expect allocations.

Although this was not a problem for performance I would really appreciate if someone could explain these allocations.

The compiler is not specializing f in f2. This solves the problem:

function f2(f::F, x) where F
    s = 0.0
    for j in 1:100
        s += f1(f, x)
    end
    s
end
2 Likes

See also: https://docs.julialang.org/en/v1/manual/performance-tips/#Be-aware-of-when-Julia-avoids-specializing

3 Likes