-
Notifications
You must be signed in to change notification settings - Fork 21
Closed
Description
using BenchmarkTools
using ConstructionBase
struct A
x::Int
y::Int
end
struct B
x::Int
y::Union{Nothing, Int}
end
function update(x)
setproperties(x, (; x = x.x + 1))
end
function update2(x::T) where T
T(x.x + 1, x.y)
end
println("Type without union")
@btime update($(Ref(A(1, 2)))[])
@btime update2($(Ref(A(1, 2)))[])
println("Type with union")
@btime update($(Ref(B(1, 2)))[])
@btime update2($(Ref(B(1, 2)))[])Results 1.3.0
Type without union
1.182 ns (0 allocations: 0 bytes)
1.182 ns (0 allocations: 0 bytes)
Type with union
381.271 ns (6 allocations: 176 bytes)
12.597 ns (0 allocations: 0 bytes)
Results 1.2.1
Type without union
1.182 ns (0 allocations: 0 bytes)
1.182 ns (0 allocations: 0 bytes)
Type with union
12.597 ns (0 allocations: 0 bytes)
12.597 ns (0 allocations: 0 bytes)
This appears to be due to the change to remove the use of generated functions for setproperties. Whereas before it would generate the equivalent of a hand rolled function (update2), now it relies on going through named tuples for its merging logic. The issue being, getproperties is type unstable in the presence of union fields. In this example:
x = B(1, 2)
@code_warntype ConstructionBase.setproperties_object(x, (; x = x.x + 1))Outputs
MethodInstance for ConstructionBase.setproperties_object(::Main.Foo.B, ::NamedTuple{(:x,), Tuple{Int64}})
from setproperties_object(obj, patch) in ConstructionBase at /home/christian/.julia/dev/ConstructionBase/src/ConstructionBase.jl:145
Arguments
#self#::Core.Const(ConstructionBase.setproperties_object)
obj::Main.Foo.B
patch::NamedTuple{(:x,), Tuple{Int64}}
Locals
nt_new::NamedTuple{(:x, :y)}
nt::NamedTuple{(:x, :y), _A} where _A<:Tuple{Int64, Union{Nothing, Int64}}
Body::Main.Foo.B
1 ─ nothing
│ (nt = ConstructionBase.getproperties(obj))
│ (nt_new = ConstructionBase.merge(nt, patch))
│ ConstructionBase.validate_setproperties_result(nt_new, nt, obj, patch)
│ %5 = ConstructionBase.typeof(obj)::Core.Const(Main.Foo.B)
│ %6 = ConstructionBase.constructorof(%5)::Core.Const(Main.Foo.B)
│ %7 = ConstructionBase.Tuple(nt_new)::Tuple
│ %8 = Core._apply_iterate(Base.iterate, %6, %7)::Main.Foo.B
└── return %8jw3126, aplavin and serenity4
Metadata
Metadata
Assignees
Labels
No labels