Refs #35102 -- Optimized Expression.identity used for equality and hashing.

inspect.signature() is quite slow and produces the same object for each
instance of the same class as they share their __init__ method which
makes it a prime candidate for caching.

Thanks Anthony Shaw for the report.
This commit is contained in:
Simon Charette 2024-01-13 14:21:36 -05:00 committed by Mariusz Felisiak
parent 92d6cff6a2
commit d074c7530b
1 changed files with 9 additions and 4 deletions

View File

@ -14,7 +14,7 @@ from django.db.models import fields
from django.db.models.constants import LOOKUP_SEP
from django.db.models.query_utils import Q
from django.utils.deconstruct import deconstructible
from django.utils.functional import cached_property
from django.utils.functional import cached_property, classproperty
from django.utils.hashable import make_hashable
@ -485,13 +485,18 @@ class BaseExpression:
class Expression(BaseExpression, Combinable):
"""An expression that can be combined with other expressions."""
@classproperty
@functools.lru_cache(maxsize=128)
def _constructor_signature(cls):
return inspect.signature(cls.__init__)
@cached_property
def identity(self):
constructor_signature = inspect.signature(self.__init__)
args, kwargs = self._constructor_args
signature = constructor_signature.bind_partial(*args, **kwargs)
signature = self._constructor_signature.bind_partial(self, *args, **kwargs)
signature.apply_defaults()
arguments = signature.arguments.items()
arguments = iter(signature.arguments.items())
next(arguments)
identity = [self.__class__]
for arg, value in arguments:
if isinstance(value, fields.Field):