-
-
Notifications
You must be signed in to change notification settings - Fork 8.3k
py/objtype: Add support for __set_name__. (dict-copy version) #16816
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
base: master
Are you sure you want to change the base?
Conversation
f48eadc
to
14fa945
Compare
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #16816 +/- ##
=======================================
Coverage 98.44% 98.44%
=======================================
Files 171 171
Lines 22192 22223 +31
=======================================
+ Hits 21847 21878 +31
Misses 345 345 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Code size report:
|
ba1d031
to
003d4ff
Compare
I've done some benchmarking using a new suite of internalbench class creation benchmarks (see PR #16825) and have compared the benchmark times from the base branch to this branch. There's a lot of noise in this (I'll see if I can run these on real hardware at some point), but overall this patch makes processing classes take about 30% longer -- though with the amount of noise it's a coin flip whether the code was actually faster than #16806 or just luckier.
There were also two other benchmark tests that got concerningly slower:
None of the other tests in their families seemed to be affected, but my tests for #15503 and #16806 both showed |
003d4ff
to
1c0b2ff
Compare
Just updated this to instead make its own copy of @dpgeorge Does anything extra need to be done to guarantee that objects referenced in the table I'm allocating on the stack can't be garbage collected? The If a descriptor's Outside of this The only thing kinda close is in |
Actually, for that matter... if what I'm worrying about is the case, the class being initialized could itself end up being collected before its returned, even without this patch. The only pointers to the class object until EDIT: After some experimentation I've determined that this (the class weirdness at least) is at least, much harder to trigger than I originally imagined, if it's possible; but I did uncover another very weird behavioral difference. On master: class A:
def __get__(self, instance, owner=None):
print("A")
class B:
__get__ = A()
print("C")
class C:
x = B()
(I have no idea how it is that |
Signed-off-by: Anson Mansfield <amansfield@mantaro.com>
Signed-off-by: Anson Mansfield <amansfield@mantaro.com>
Signed-off-by: Anson Mansfield <amansfield@mantaro.com>
02d9895
to
6720e77
Compare
Signed-off-by: Anson Mansfield <amansfield@mantaro.com>
Signed-off-by: Anson Mansfield <amansfield@mantaro.com>
This is my least favourite of the implementations. It's stack heavy and unconditionally allocates. I think #16806 could be made to be simpler than this version. |
Summary
This implements the alternative "flat dict copy" logic discussed in #16806 as another way to eliminate the modify-while-iterating hazard in the original
__set_name__
implementation (#15503).Testing
This feature was developed test-first. All automated tests pass, including additional tests added to verify the additional behavior around whether
__set_name__
is called even on descriptors that another__set_name__
removes beforehand.Trade-offs and Alternatives
This version has significantly lower code complexity than #16806, but at the cost of a larger runtime memory footprint. It's still a bit more complex than #15503, though.