diff options
author | Jens W. Klein <jk@kleinundpartner.at> | 2020-01-24 17:01:06 +0100 |
---|---|---|
committer | Jens W. Klein <jk@kleinundpartner.at> | 2020-01-24 17:26:45 +0100 |
commit | fbadf4a8ab389afd87dda3032a2f1066d766a6b8 (patch) | |
tree | ec1af913aafcc0e8ff960841511a88996c4be917 | |
parent | 02e11f214ce04e9cebc7418be8fe890df23a338c (diff) | |
download | zope-interface-fbadf4a8ab389afd87dda3032a2f1066d766a6b8.tar.gz |
Improve InterfaceClass __hash__ performance
-rw-r--r-- | CHANGES.rst | 7 | ||||
-rw-r--r-- | src/zope/interface/interface.py | 14 |
2 files changed, 16 insertions, 5 deletions
diff --git a/CHANGES.rst b/CHANGES.rst index c5de832..9205b88 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -17,6 +17,13 @@ an undocumented private C API function, and helps make some instances require less memory. See `PR 154 <https://github.com/zopefoundation/zope.interface/pull/154>`_. +- Performance optimization of ``__hash__`` method on ``InterfaceClass``. + The method is called very often (i.e several 100.000 times on a Plone 5.2 + startup). Because the hash value never changes it can be cached. + This improves test performance from 0.614s down to 0.575s (1.07x faster). + In a real world Plone case a reindex index came down from 402s to 320s (1.26x faster). + See `PR 156 <https://github.com/zopefoundation/zope.interface/pull/156>`_. + 4.7.1 (2019-11-11) ================== diff --git a/src/zope/interface/interface.py b/src/zope/interface/interface.py index e72c2bd..d832602 100644 --- a/src/zope/interface/interface.py +++ b/src/zope/interface/interface.py @@ -538,11 +538,15 @@ class InterfaceClass(Element, InterfaceBase, Specification): return (n1 > n2) - (n1 < n2) def __hash__(self): - d = self.__dict__ - if '__module__' not in d or '__name__' not in d: # pragma: no cover - warnings.warn('Hashing uninitialized InterfaceClass instance') - return 1 - return hash((self.__name__, self.__module__)) + try: + return self._cached_hash + except AttributeError: + try: + self._cached_hash = hash((self.__name__, self.__module__)) + except AttributeError: # pragma: no cover + warnings.warn('Hashing uninitialized InterfaceClass instance') + return 1 + return self._cached_hash def __eq__(self, other): c = self.__cmp(other) |