# Performance of keeping a model "reference"

**URL:** <https://discourse.julialang.org/t/performance-of-keeping-a-model-reference/81903>\
**Category:** Optimization (Mathematical)\
**Tags:** jump\
**Created:** [May 30, 2022, 7:54am UTC](https://discourse.julialang.org/t/performance-of-keeping-a-model-reference/81903 "2022-05-30T07:54:18Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![sstroemer](https://avatars.discourse-cdn.com/v4/letter/s/a88e4f/32.png) [@sstroemer](https://discourse.julialang.org/u/sstroemer)\
**Post date:** [May 30, 2022, 7:54am UTC](https://discourse.julialang.org/t/performance-of-keeping-a-model-reference/81903/1 "2022-05-30T07:54:18Z")

</div>

I have asked about the related idea behind my problem [over here](https://discourse.julialang.org/t/efficient-parent-reference-for-structs/81194/7), 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

1. keeping that as field of the `struct`
2. not keeping it at all
3. 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:

1. 209609
2. 207609
3. 212609

Allocations without `.ext`:

1. 202119
2. 202119

* * *

MWE:

```julia
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()

```

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [May 31, 2022, 7:48pm UTC](https://discourse.julialang.org/t/performance-of-keeping-a-model-reference/81903/2 "2022-05-31T19:48:19Z")

</div>

Every variable already keeps a reference to the `Model`, so storing an additional one should have minimal impact. (If you have a variable, you can use `owner_model(x)` to retrieve the model.)

I don’t really understand the differences in allocations though. I’d just pick the one that you like working with the best. Only worry about this if it is a computational bottleneck.

---

<div class="post-metadata">

**Author:** ![sstroemer](https://avatars.discourse-cdn.com/v4/letter/s/a88e4f/32.png) [@sstroemer](https://discourse.julialang.org/u/sstroemer)\
**Post date:** [June 1, 2022, 7:39am UTC](https://discourse.julialang.org/t/performance-of-keeping-a-model-reference/81903/3 "2022-06-01T07:39:23Z")

</div>

Thanks for the insight! - especially since I didn’t know about `owner_model(x)` and that’s already coming in handy somewhere else! 😀
