summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens W. Klein <jk@kleinundpartner.at>2020-01-27 11:09:05 +0100
committerGitHub <noreply@github.com>2020-01-27 11:09:05 +0100
commiteeaacb6d6a0589ea9b969655e9624209913d5e47 (patch)
tree03d25c510588ee10a27b523262c7bc6edbbb3e79
parent02e11f214ce04e9cebc7418be8fe890df23a338c (diff)
parent32726faad8ac4f131b55e5b6785c885f6f2eb1ef (diff)
downloadzope-interface-eeaacb6d6a0589ea9b969655e9624209913d5e47.tar.gz
Merge pull request #156 from zopefoundation/hash_performance
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..7a852f8 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._v_cached_hash
+ except AttributeError:
+ try:
+ self._v_cached_hash = hash((self.__name__, self.__module__))
+ except AttributeError: # pragma: no cover
+ warnings.warn('Hashing uninitialized InterfaceClass instance')
+ return 1
+ return self._v_cached_hash
def __eq__(self, other):
c = self.__cmp(other)