-
-
Notifications
You must be signed in to change notification settings - Fork 32.1k
gh-135385: Fix memory regression for classes with both __slots__ and __dict__ #135389
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: main
Are you sure you want to change the base?
Conversation
This comment was marked as resolved.
This comment was marked as resolved.
75490c7
to
9d82a67
Compare
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.
No need to force-push, we squash at the end.
Misc/NEWS.d/next/Core_and_Builtins/2025-06-11-21-40-21.gh-issue-135385.e2TFON.rst
Outdated
Show resolved
Hide resolved
…e-135385.e2TFON.rst Co-authored-by: Peter Bierma <[email protected]>
I'm not that familiar with the underlying type machinery. Does the fix also work for the opposite: class _NoSlots:
pass
class Point3D_BrokenSlots(_NoSlots):
__slots__ = ("x", "y")
def __init__(self, x, y, z):
self.x, self.y, self.z = x, y, z |
Adding label per:
|
EDIT: Apologies, I commited my pr before seeing Eclips4's comment. I have since confirmed locally by compiling and testing the
main
branch that this issue is indeed fixed there.This PR should NOT be merged or backported. It would fail to fix the bug on 3.13 and could potentially mask the real issue or introduce other instabilities.
This patch fixes a significant memory regression in Python 3.13 where classes that inherit __slots__ but also have a __dict__ consume ~4x more memory than necessary.
The root cause was that such subclasses incorrectly inherited a non-zero tp_itemsize from their base. This prevented the Py_TPFLAGS_INLINE_VALUES flag from being set, disabling the key-sharing dictionary optimization.
The fix, located in Objects/typeobject.c, adjusts the logic to ensure a subclass only inherits a non-zero tp_itemsize if it defines its own _slots_. Otherwise, tp_itemsize is correctly set to 0, re-enabling the memory optimization.
test:
benchmark:
__slots__
and__dict__
have much larger size than needed (up to 4x) on Python 3.13 #135385