I want to use the @unpack_STRUCT
macro in Parameters.jl to unpack all fields of a mutable struct, but I need it to be type stable. Here is an example:
using Parameters, BenchmarkTools
@with_kw mutable struct S @deftype Float64
a;b;c;d
end
function f!(s::S)
@unpack a,b,c = s
d = a*b*c
@pack s = d
return s
end
function g!(s::S)
@unpack_S s
d = a*b*c
@pack_S s
end
In this example, f!(s)
is type stable but g!(s)
is not.
julia> s = S(2,3,4,1); @btime f!(s);
16.682 ns (0 allocations: 0 bytes)
julia> s = S(2,3,4,1); @btime g!(s);
4.641 μs (54 allocations: 3.13 KiB)
julia> @code_warntype g!(s)
Variables:
#self# <optimized out>
s@_2::S
a::Float64
b::Float64
c::Float64
d::Float64
s@_7::Any
Body:
begin
s@_7::Any = s@_2::S
a::Float64 = (Core.getfield)(s@_7::S, :a)::Float64
b::Float64 = (Core.getfield)(s@_7::S, :b)::Float64
c::Float64 = (Core.getfield)(s@_7::S, :c)::Float64
d::Float64 = (Core.getfield)(s@_7::S, :d)::Float64 # line 15:
d::Float64 = (Base.mul_float)((Base.mul_float)(a::Float64, b::Float64)::Float64, c::Float64)::Float64 # line 16:
SSAValue(0) = $(Expr(:invoke, MethodInstance for (::Parameters.#kw##reconstruct)(::Array{Any,1}, ::Parameters.#reconstruct, ::S), :($(QuoteNode(Parameters.#reconstruct))), :($(Expr(:invoke, MethodInstance for vector_any(::Any, ::Vararg{Any,N} where N), :(Base.vector_any), :(:a), :(a), :(:b), :(b), :(:c), :(c), :(:d), :(d)))), :($(QuoteNode(Parameters.reconstruct))), :(s@_7::S)))
s@_7::Any = SSAValue(0)
return SSAValue(0)
end::Any
Is there a way to make g!(s)
type stable or do I need to list individual fields as I did in f!(s)
?