Setfield! allocates memory when setting Float64 values

A variant of the @generated function approach could be to generate “somehow” a “set_field!” function explicitly with a macro once for every type involved and then call these functions. Below is a test (replacing the macro by manually providing the set_fields! functions for simplicity):

module Test3

mutable struct Vars1
    v1::Float64
    v2::Float64
    v3::Float64
    v4::Float64
    v5::Float64
end
function set_fields!(v::Vars1, x::Vector{Float64}, j::Int)
    v.v1 = x[j]
    v.v2 = x[j+1]
    v.v3 = x[j+2]
    v.v4 = x[j+3]
    v.v5 = x[j+4]
end

mutable struct Vars2
    r1::Float64
    r2::Float64
    r3::Float64
    r4::Float64
    r5::Float64
end
function set_fields!(v::Vars2, x::Vector{Float64}, j::Int)
    v.r1 = x[j]
    v.r2 = x[j+1]
    v.r3 = x[j+2]
    v.r4 = x[j+3]
    v.r5 = x[j+4]
end

function copy_from_x!(vars::Vector{Any}, x::Vector{Float64})::Nothing
    j = 1
    for v in vars
        set_fields!(v, x, j)
        j = j+5
    end
    return nothing;
end

# Build Data structure (vector of Vars1 and Vars2 objects)
function buildVars(nc::Int)
    v1 = Vars1(1.0, 2.0, 3.0, 4.0, 5.0)
    r1 = Vars2(6.0, 7.0, 8.0, 9.0, 10.0)
    vars = Any[]
    for i = 1:nc
        push!(vars, deepcopy(v1))
        push!(vars, deepcopy(r1))
    end
    return vars
end

nc=2; vars = buildVars(nc);  x = randn(nc*10)
println("\nnc = $nc")
      copy_from_x!(vars, x)
@time copy_from_x!(vars, x)


nc=10; vars = buildVars(nc);  x = randn(nc*10)
println("\nnc = $nc")
@time copy_from_x!(vars, x)


nc=100; vars = buildVars(nc);  x = randn(nc*10)
println("\nnc = $nc")
@time copy_from_x!(vars, x)


nc=10000; vars = buildVars(nc);  x = randn(nc*10)
println("\nnc = $nc")
@time copy_from_x!(vars, x)

end

The output is:

nc = 2
  0.000003 seconds (4 allocations: 160 bytes)

nc = 10
  0.000003 seconds (4 allocations: 160 bytes)

nc = 100
  0.000005 seconds (4 allocations: 160 bytes)

nc = 10000
  0.000184 seconds (4 allocations: 160 bytes)

So this looks good with respect to memory (no unnecessary memory allocated).

However, multiple dispatch is used in a way so that functions set_fields! are resolved at runtime and it seems not possible to avoid this. The question is whether there will be issues if many different types are used in vector vars. In this discourse discussion a similar topic seems to be discussed and when I read this correctly, there can be in fact a substantial overhead of multiple dispatch in such a case.