# Adding parameters to function definition avoids allocations

I’m trying to get a small piece of code that I’ll run millions of times to run without allocations. There is a small allocation that I cannot understand the cause of (for example, using Profile.Allocs cannot attribute the allocation to anything, even with a sample rate of 100%), but that I can avoid by adding parameters to a specific function definition. Unfortunately, in practice I can’t use the parameters because I need to support the inputs being of different types.

I’ve attempted to write a MWE to highlight the problem. Unfortunately, it doesn’t exhibit the same behaviour - the allocations happen even with the parameters. I don’t yet know why it’s different. Perhaps it’s because the code I’m using is in a package I’m writing - I have no idea. However, the M(non-)WE shows the syntax I mean, so perhaps someone will be able to explain the behaviour. Here’s the code and output:

``````using BenchmarkTools
using StaticArrays

struct Residual{T<:Number}
meas::SVector{2, T}
end

struct Transform{T<:Number}
rot::SMatrix{3, 3, T}
trans::SVector{3, T}
end

struct Point{T<:Number}
point::SVector{3, T}
end

function project(p::Point)
return SVector{2}(p.point[1], p.point[2]) ./ p.point[3]
end

function transform(t::Transform, p::Point)
return project(Point(t.rot * p.point + t.trans))
end

function computeresidual1(r::Residual, t::Transform, p::Point)
return transform(t, p) - r.meas
end

function computeresidual2(r::Residual{T}, t::Transform{T}, p::Point{T})::SVector{2, T} where T <: Real
return transform(t, p) - r.meas
end

r = Residual(randn(SVector{2, Float64}))
t = Transform(randn(SMatrix{3, 3, Float64}), randn(SVector{3, Float64}))
p = Point(randn(SVector{3, Float64}))

@btime computeresidual1(\$r, \$t, \$p)
@btime computeresidual2(\$r, \$t, \$p)
``````

julia> 327.487 ns (8 allocations: 256 bytes)
julia> 446.551 ns (8 allocations: 256 bytes)

In my own case, the call to the function with parameters specified (computeresidual2), has zero allocations. Here it not only still has allocations, it’s also slower; the speed becomes the same if I don’t specify the output type in the function declaration.

I’m running Julia 1.8.2

The problem is that `SMatrix{3, 3, T}` is not concrete, since it is missing its fourth parameter `L` which is the total length of the array. Replace it with `SMatrix{3, 3, T, 9}` and the issue should be gone.

Ah, thanks. Yes, that’s the problem causing the allocations in the MWE.
I’ve realised that that’s not the actual problem in my code sadly. Hence why the parameters make no difference. I’ll fix the MWE, and try asking again.

I’ve now created a working MWE and posted it here.