gh-74690: Optimise isinstance() and issubclass() calls against runtime-checkable protocols by avoiding costly super() calls (#112708)

This commit is contained in:
Alex Waygood 2023-12-04 15:41:41 +00:00 committed by GitHub
parent 9560e0d6d7
commit c718ab92a5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 16 additions and 3 deletions

View file

@ -1782,6 +1782,14 @@ def _pickle_pskwargs(pskwargs):
del _pickle_psargs, _pickle_pskwargs
# Preload these once, as globals, as a micro-optimisation.
# This makes a significant difference to the time it takes
# to do `isinstance()`/`issubclass()` checks
# against runtime-checkable protocols with only one callable member.
_abc_instancecheck = ABCMeta.__instancecheck__
_abc_subclasscheck = ABCMeta.__subclasscheck__
class _ProtocolMeta(ABCMeta):
# This metaclass is somewhat unfortunate,
# but is necessary for several reasons...
@ -1841,7 +1849,7 @@ def __subclasscheck__(cls, other):
"Instance and class checks can only be used with "
"@runtime_checkable protocols"
)
return super().__subclasscheck__(other)
return _abc_subclasscheck(cls, other)
def __instancecheck__(cls, instance):
# We need this method for situations where attributes are
@ -1850,7 +1858,7 @@ def __instancecheck__(cls, instance):
return type.__instancecheck__(cls, instance)
if not getattr(cls, "_is_protocol", False):
# i.e., it's a concrete subclass of a protocol
return super().__instancecheck__(instance)
return _abc_instancecheck(cls, instance)
if (
not getattr(cls, '_is_runtime_protocol', False) and
@ -1859,7 +1867,7 @@ def __instancecheck__(cls, instance):
raise TypeError("Instance and class checks can only be used with"
" @runtime_checkable protocols")
if super().__instancecheck__(instance):
if _abc_instancecheck(cls, instance):
return True
getattr_static = _lazy_load_getattr_static()

View file

@ -0,0 +1,5 @@
Speedup :func:`isinstance` checks by roughly 20% for
:func:`runtime-checkable protocols <typing.runtime_checkable>`
that only have one callable member.
Speedup :func:`issubclass` checks for these protocols by roughly 10%.
Patch by Alex Waygood.