Efficiently Retrieving Variable Values after Gurobi optimization with JuMP

I just took a slight look at the procedure of JuMP.value. To be honest, it’s highly complex—no wonder it’s slow.

I would like to ask if JuMP could provide a pass-by-address method, besides the existing pass-by-value method?

I wrote one

import JuMP, Gurobi
const GRB_ENV = Gurobi.Env()

function unsafe_array_value!(X, x)
    o = JuMP.unsafe_backend(JuMP.owner_model(x[1]))
    for j = eachindex(X)
        Gurobi.GRBgetdblattrelement(o, "X", 
        Gurobi.c_column(o, JuMP.index(x[j])),
        view(X, j))
    end
end

function unsafe_test()
    m = JuMP.Model(() -> Gurobi.Optimizer(GRB_ENV))
    JuMP.@variable(m, x[i = 1:3, j = 1:4] >= i + j)
    JuMP.@objective(m, Min, sum(x))
    JuMP.optimize!(m)
    X = similar(x, Float64)
    unsafe_array_value!(X, x)
    X
end

unsafe_test()

For direct_model, do this

function scalar!(X, j, m, x)
    o = m.moi_backend
    Gurobi.GRBgetdblattrelement(o, "X", Gurobi.c_column(o, JuMP.index(x[j])), view(X, j))
end;
value!(X, m, x) = foreach(j -> scalar!(X, j, m, x), eachindex(X));
function solve_mst_and_up_value!(model, s, θ, β)
    JuMP.optimize!(model)
    JuMP.termination_status(model) == JuMP.OPTIMAL || error()
    s.ub.x = JuMP.objective_bound(model)
    value!(s.β, model, β)
    value!(s.θ, model, θ)
end;
function shot!(ref; model = model, θ = θ, β = β, rEF = rEF)
    s = rEF.x
    @lock mst_lock solve_mst_and_up_value!(model, s, θ, β) # `s` gets updated/mutated here
    s_tmp = ref.x
    setfield!(ref, :x, s) # the ref gets updated here
    setfield!(rEF, :x, s_tmp)
end;