summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens W. Klein <jk@kleinundpartner.at>2020-01-24 17:01:06 +0100
committerJens W. Klein <jk@kleinundpartner.at>2020-01-24 17:26:45 +0100
commitfbadf4a8ab389afd87dda3032a2f1066d766a6b8 (patch)
treeec1af913aafcc0e8ff960841511a88996c4be917
parent02e11f214ce04e9cebc7418be8fe890df23a338c (diff)
downloadzope-interface-fbadf4a8ab389afd87dda3032a2f1066d766a6b8.tar.gz
Improve InterfaceClass __hash__ performance
-rw-r--r--CHANGES.rst7
-rw-r--r--src/zope/interface/interface.py14
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)