-
Notifications
You must be signed in to change notification settings - Fork 22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve performance of setproperties
/getproperties
for structs with unions
#91
Conversation
Codecov ReportAttention: Patch coverage is
❗ Your organization needs to install the Codecov GitHub app to enable full functionality. Additional details and impacted files@@ Coverage Diff @@
## master #91 +/- ##
==========================================
- Coverage 25.49% 1.76% -23.73%
==========================================
Files 5 5
Lines 153 170 +17
==========================================
- Hits 39 3 -36
- Misses 114 167 +53 ☔ View full report in Codecov by Sentry. |
All tests pass, the two downstream failures on nightly don't seem to be related to this PR. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice that it's possible to be both fast and correct :)
The Setfield failure is due to some timing comparison. The test passes locally for me on the same Julia version, with much lower timings (7ns and 1ns), so I'm guessing it might just be some runner performance inconsistency. |
Does It probably won't need that allocation in practice. |
Indeed, the allocation is removed: julia> struct C
a::Union{Nothing, String}
b::UInt32
end
julia> f(x) = begin; props = getproperties(x); props.b end
f (generic function with 2 methods)
julia> x = C("hello", 6)
C("hello", 0x00000006)
julia> @btime f($x)
1.613 ns (0 allocations: 0 bytes)
0x00000006 |
Any objections to merging this? AFAIK this should no longer break anything and only result in performance improvements, particularly so for If the small changes to |
pnames = fieldnames(patch) | ||
for fname in fieldnames(obj) | ||
source = fname in pnames ? :patch : :obj | ||
push!(args, :(getproperty($source, $(QuoteNode(fname))))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getfield
instead? as the function is named setfields_object
here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The previous implementation used getproperty
, I thought best to stay in line with it. Notably, the edge cases where we can't distinguish overloaded properties from fields is handled the same way as before.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, the field/property handling in the package should be improved even further in the future, but I agree that for now the minimal change is best
I guess there are no objections here, @jw3126 @rafaqz? |
Should be all good now, thanks! |
Thanks, should be registered soon! |
Addresses #55.
These changes make use of generated functions in the case where properties are fields, both for
getproperties
andsetproperties
.In terms of performance, see
getproperties
still allocates, this is due to using aNamedTuple
that contains a union for one of its fields. I guess one could force theUnion
to be formed on the outside, e.g.Union{NamedTuple{....}, NamedTuple{...}}
, but I think the current state is fine and has the benefit of simplicity.setproperties
is as fast as one would expect, at least.The
"no allocs S2"
testset captures the performance improvements of this PR, failing on currentmaster
.