gh-135385: Fix memory regression for classes with both __slots__ and __dict__ #135389
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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