gh-92810: Reduce memory usage by ABCMeta.__subclasscheck__ (alternative2)#150540
Open
dolfinus wants to merge 4 commits into
Open
gh-92810: Reduce memory usage by ABCMeta.__subclasscheck__ (alternative2)#150540dolfinus wants to merge 4 commits into
dolfinus wants to merge 4 commits into
Conversation
|
Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool. If this change has little impact on Python users, wait for a maintainer to apply the |
Documentation build overview
|
This was referenced May 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
_abc._abc_subclasscheckhas very poor performance and (I think) a memory leak #92810Alternative implementation of #131914 which does not check
__subclasses__recursively.To handle cases like:
which previously were implemented via recursive
__subclasses__check, methodcls.register(subclass)is callingsuper(cls).register(subclass)recursively ("bubble-up" registration to all the parents).For benchmark from #131914:
isinstance(child, Parent)4MiB...15MiB
2MiB...15MiB
11MiB...24MiB
11MiB...24MiB
issubclass(Child, Parent)0MiB...1MiB
0MiB...1MiB
6MiB...8MiB
5MiB...8MiB
isinstance(child, Grandparent)0MiB...2MiB
1MiB...1MiB
4MiB...7MiB
4MiB...7MiB
issubclass(Child, Grandparent)0MiB
0MiB
0MiB...1MiB
0MiB...1MiB
not isinstance(child, Sibling)4MiB...14MiB
3MiB...14MiB
13MiB...23MiB
13MiB...22MiB
not issubclass(Child, Sibling)1MiB
1MiB...2MiB
8MiB...10MiB
9MiB...11MiB
not isinstance(child, Cousin)1MiB...2MiB
1MiB...2MiB
7MiB...9MiB
7MiB...10MiB
not issubclass(Child, Cousin)0MiB
0MiB...1MiB
4MiB
4MiB...5MiB
not isinstance(child, Uncle)6174MiB...6333MiB
0MiB...1MiB
4382MiB...4422MiB
6MiB
not issubclass(Child, Uncle)6171MiB
0MiB
4380MiB
4MiB...5MiB
Memory increment is measured during
isinstance()/issubclass()calls, not during preparation, like class creation or registration where actual registry allocation is performed. So memory usage in tables below is almost always 0.Timing drop in _py_abc implementation for 2 first rows is due to
if subclass in cls._abc_registry:check added to match _abc.c implementation.isinstance(child, Parent.register)0MiB
0MiB
0MiB
0MiB
issubclass(Child, Parent.register)0MiB
0MiB
0MiB
0MiB
isinstance(child, Grandparent.register)0MiB
0MiB
0MiB
0MiB
issubclass(Child, Grandparent.register)0MiB
0MiB
0MiB
0MiB
not isinstance(child, Sibling.register)0MiB
1MiB
0MiB
2MiB
not issubclass(Child, Sibling.register)0MiB
1MiB
0MiB
2MiB
not isinstance(child, Cousin.register)0MiB
2MiB
0MiB
3MiB
not issubclass(Child, Cousin.register)0MiB
2MiB
0MiB
3MiB
not isinstance(child, Uncle.register)0MiB
2MiB
0MiB
3MiB
not issubclass(Child, Uncle.register)0MiB
2MiB
0MiB
3MiB
Just to check that nothing is broken:
not isinstance(child, Unrelated)0MiB
0MiB
0MiB
0MiB
not issubclass(Child, Unrelated)0MiB
0MiB
0MiB
0MiB
not isinstance(child, UnrelatedABC)0MiB
0MiB
0MiB
0MiB
not issubclass(Child, UnrelatedABC)0MiB
0MiB
0MiB
0MiB
Flamegraphs for
_py_abcimpl and testissubclass_uncle(the most time and memory consuming case onmain):main_vs_pr150540.tar.gz