Skip to content

Commit

Permalink
fix set_property alloc
Browse files Browse the repository at this point in the history
  • Loading branch information
ACEsuit committed May 28, 2024
1 parent d5364f0 commit a9efea6
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 7 deletions.
32 changes: 29 additions & 3 deletions src/states.jl
Original file line number Diff line number Diff line change
Expand Up @@ -203,11 +203,37 @@ vstate_type(S::Type, X::XState) = vstate_type(zero(S), X)

## ---------- a simple copying setter-like functionality

function set_property(x::S, s::Symbol, val) where {S}
nt = _x(x)
return S((; nt..., s => val,))
# this seems allocating, unclear why hence a generated implementation below

@generated function set_property(x::TX, s::Symbol, val) where {TX <: XState}
SYMS, TT = _symstt(TX)
code = "$(nameof(TX))("
for i = 1:length(SYMS)
sym = SYMS[i]
code *= "$sym = (:$sym == s ? val : x.$sym)::(typeof(x.$sym)), "
end
code *= ")"
quote
$(Meta.parse(code))
end
end

@generated function set_property(x::TX, ::Val{sym1}, val1) where {TX <: XState, sym1}
SYMS, TT = _symstt(TX)
code = "$(nameof(TX))("
for (sym, T) in zip(SYMS, TT.types)
if sym == sym1
code *= "$sym = val1, "
else
code *= "$sym = x.$sym, "
end
end
code *= ")"
quote
$(Meta.parse(code))
end
end


## ---------- explicit real/complex conversion
# this feels a bit like a hack but might be unavoidable;
Expand Down
7 changes: 3 additions & 4 deletions test/test_atomsbase.jl
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,8 @@ DP.set_positions!(aos1, X)
DP.set_position!(aos1, 1, 𝐫1)
@test position(aos1, 1) == 𝐫1

@allocated DP.set_position(x, 𝐫1)
@allocated DP.set_positions!(aos1, X)
@allocated DecoratedParticles.set_position(x, 𝐫1)
@test (@allocated DP.set_positions!(aos1, X)) == 0

##

Expand All @@ -112,8 +112,7 @@ DP.set_positions!(soa, X)
DP.set_position!(soa, 1, 𝐫1)
@test position(soa, 1) == 𝐫1

# much nicer behaved for now! no allocation
@allocated DP.set_positions!(soa, X)
@test (@allocated DP.set_positions!(soa, X)) == 0

##

Expand Down
29 changes: 29 additions & 0 deletions test/test_states.jl
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,32 @@ let Ys = Ys, Xs = Xs, a = a
println(@test nalloc == 0)
end

##

x = PState(a = 1.0, b = 2, c = true)
y = DP.set_property(x, :a, 2.3)
z = DP.set_property(x, Val(:a), 2.3)
@test y.a == 2.3 && y.b == x.b && y.c == x.c
@test z.a == 2.3 && z.b == x.b && z.c == x.c
@test y == z

function transform_states!(Xs, sym)
for i = 1:length(Xs)
xi = Xs[i]
Xs[i] = DecoratedParticles.set_property(xi, sym, rand())
end
return nothing
end

# test that there are no allocations
Xs = [ PState(a = 1.0, b = 2, c = true) for _ = 1:1000 ]
transform_states!(Xs, :a)
@test (@allocated transform_states!(Xs, :a)) == 0
transform_states!(Xs, Val{:a}())
@test (@allocated transform_states!(Xs, Val{:a}())) == 0

# the two codes are essentially equivalent!!
# using BenchmarkTools
# @btime transform_states!($Xs, $(:a))
# @btime transform_states!($Xs, Val{:a}())

0 comments on commit a9efea6

Please sign in to comment.