I have asked about the related idea behind my problem over here, but since no conclusion could be drawn, I’ve constructed a little test. That’s where things got weird - I am unsure why the result looks the way they do, and now feel like I am doing something wrong.

Short explanation, the full code is posted below. Basically I am looking to integrate a “reference” to the current `JuMP.Model`

being built into every component (the “components” are some kind of building blocks of this model). That’s why I am comparing the performance of

- keeping that as field of the
`struct`

- not keeping it at all
- keeping it as field of the
`struct`

but only as`Ref`

The initial test showed that `2.`

resulted in two allocations less than `1.`

(kind of expected?), while `3.`

results in three allocations more (did not expect that?).

Now, I am adding all components to the `.ext`

dictionary, and I thought that would not influence the 3 different ways, but something strange happens: `1.`

and `2.`

result in the same amount of allocations if I do not save the components into `.ext`

. And now I am completely lost on why this happens…

Really glad for any insights (probably about me misunderstanding how Julia handles something…)!

Allocations:

- 209609
- 207609
- 212609

Allocations without `.ext`

:

- 202119
- 202119

MWE:

```
using JuMP
using BenchmarkTools
Base.@kwdef mutable struct Component1
model::JuMP.Model
var::Union{Vector{JuMP.VariableRef}, Nothing} = nothing
bound::Float64
end
Base.@kwdef mutable struct Component2
var::Union{Vector{JuMP.VariableRef}, Nothing} = nothing
bound::Float64
end
Base.@kwdef mutable struct Component3
model::Ref{JuMP.Model}
var::Union{Vector{JuMP.VariableRef}, Nothing} = nothing
bound::Float64
end
function foo1()
m = JuMP.Model()
set_string_names_on_creation(m, false)
m.ext[:components] = [Component1(model=m, bound=rand()) for _ in 1:1000]
for comp in m.ext[:components]
comp.var = @variable(comp.model, [t=1:100], upper_bound=comp.bound)
end
end
function foo2()
m = JuMP.Model()
set_string_names_on_creation(m, false)
m.ext[:components] = [Component2(bound=rand()) for _ in 1:1000]
for comp in m.ext[:components]
comp.var = @variable(m, [t=1:100], upper_bound=comp.bound)
end
end
function foo3()
m = JuMP.Model()
set_string_names_on_creation(m, false)
m.ext[:components] = [Component3(model=Ref(m), bound=rand()) for _ in 1:1000]
for comp in m.ext[:components]
comp.var = @variable(comp.model[], [t=1:100], upper_bound=comp.bound)
end
end
function foo1_alt()
m = JuMP.Model()
set_string_names_on_creation(m, false)
comps = [Component1(model=m, bound=rand()) for _ in 1:1000]
for comp in comps
comp.var = @variable(comp.model, [t=1:100], upper_bound=comp.bound)
end
end
function foo2_alt()
m = JuMP.Model()
set_string_names_on_creation(m, false)
comps = [Component2(bound=rand()) for _ in 1:1000]
for comp in comps
comp.var = @variable(m, [t=1:100], upper_bound=comp.bound)
end
end
@benchmark foo1()
@benchmark foo2()
@benchmark foo3()
@benchmark foo1_alt()
@benchmark foo2_alt()
```