# Setfield! allocates memory when setting Float64 values

**URL:** <https://discourse.julialang.org/t/setfield-allocates-memory-when-setting-float64-values/31811>\
**Category:** Performance\
**Created:** [December 3, 2019, 4:50pm UTC](https://discourse.julialang.org/t/setfield-allocates-memory-when-setting-float64-values/31811 "2019-12-03T16:50:43Z")\
**Posts on this page:** 1\
**Showing post:** 4

<div class="post-metadata">

**Author:** ![MartinOtter](https://avatars.discourse-cdn.com/v4/letter/m/87869e/32.png) [@MartinOtter](https://discourse.julialang.org/u/MartinOtter)\
**Post date:** [December 5, 2019, 2:52pm UTC](https://discourse.julialang.org/t/setfield-allocates-memory-when-setting-float64-values/31811/4 "2019-12-05T14:52:32Z")

</div>

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):

```julia
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:

```julia
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](https://discourse.julialang.org/t/how-to-access-shared-inherited-fields-without-paying-multiple-dispatch-performance-price/26762/12) 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.

---

_[View the full topic](https://discourse.julialang.org/t/setfield-allocates-memory-when-setting-float64-values/31811)._
