summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens W. Klein <jk@kleinundpartner.at>2020-02-04 21:50:19 +0100
committerGitHub <noreply@github.com>2020-02-04 21:50:19 +0100
commit79be400cc9a5a8525db9e7869e401aede3d01d72 (patch)
tree52f5204db8a04d5959cb58baba0a89ee818730f7
parentbe8275645900d3d598d59ef9644983a77ccc8f70 (diff)
parent1a7e4dc0c3e2bd4b1ece814efce7a34fbbf6efbf (diff)
downloadzope-interface-79be400cc9a5a8525db9e7869e401aede3d01d72.tar.gz
Merge pull request #167 from zopefoundation/lookup-performance
Performance optimization in _lookup _lookupAll and _subscriptions
-rw-r--r--CHANGES.rst8
-rw-r--r--src/zope/interface/adapter.py19
2 files changed, 21 insertions, 6 deletions
diff --git a/CHANGES.rst b/CHANGES.rst
index ae900d8..d2282c8 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -67,6 +67,14 @@
of) interface adaptation. See `issue 163
<https://github.com/zopefoundation/zope.interface/issues/163>`_.
+- Micro-optimization in `.adapter. `, `.adapter._lookupAll` and
+ `.adapter._subscriptions`: By loading components.get into a local variable
+ before entering the loop a bytcode "LOAD_FAST 0 (components)" in the loop
+ can be eliminated. In Plone, while running all tests, average speedup of
+ `_lookup`s owntime is ~5x.
+ See `PR 167 <https://github.com/zopefoundation/zope.interface/pull/167>`_.
+
+
4.7.1 (2019-11-11)
==================
diff --git a/src/zope/interface/adapter.py b/src/zope/interface/adapter.py
index 9587f9c..3b566ba 100644
--- a/src/zope/interface/adapter.py
+++ b/src/zope/interface/adapter.py
@@ -658,16 +658,21 @@ def _convert_None_to_Interface(x):
return x
def _lookup(components, specs, provided, name, i, l):
+ # this function is called very often.
+ # The components.get in loops is executed 100 of 1000s times.
+ # by loading get into a local variable the bytecode
+ # "LOAD_FAST 0 (components)" in the loop can be eliminated.
+ components_get = components.get
if i < l:
for spec in specs[i].__sro__:
- comps = components.get(spec)
+ comps = components_get(spec)
if comps:
r = _lookup(comps, specs, provided, name, i+1, l)
if r is not None:
return r
else:
for iface in provided:
- comps = components.get(iface)
+ comps = components_get(iface)
if comps:
r = comps.get(name)
if r is not None:
@@ -676,26 +681,28 @@ def _lookup(components, specs, provided, name, i, l):
return None
def _lookupAll(components, specs, provided, result, i, l):
+ components_get = components.get # see _lookup above
if i < l:
for spec in reversed(specs[i].__sro__):
- comps = components.get(spec)
+ comps = components_get(spec)
if comps:
_lookupAll(comps, specs, provided, result, i+1, l)
else:
for iface in reversed(provided):
- comps = components.get(iface)
+ comps = components_get(iface)
if comps:
result.update(comps)
def _subscriptions(components, specs, provided, name, result, i, l):
+ components_get = components.get # see _lookup above
if i < l:
for spec in reversed(specs[i].__sro__):
- comps = components.get(spec)
+ comps = components_get(spec)
if comps:
_subscriptions(comps, specs, provided, name, result, i+1, l)
else:
for iface in reversed(provided):
- comps = components.get(iface)
+ comps = components_get(iface)
if comps:
comps = comps.get(name)
if comps: