summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens W. Klein <jk@kleinundpartner.at>2020-02-04 19:50:22 +0100
committerJens W. Klein <jk@kleinundpartner.at>2020-02-04 19:55:23 +0100
commit8ab01943066bc2564efe2a2d554e71658ff88cd8 (patch)
tree7f02f9833bb0b0caef3fb17bf58145daa4a871ea
parentbe8275645900d3d598d59ef9644983a77ccc8f70 (diff)
downloadzope-interface-8ab01943066bc2564efe2a2d554e71658ff88cd8.tar.gz
iPerformace optimization in _lookup _lookupAll _subscriptionslookup-performance
-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..490712d 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.
+ cget = components.get
if i < l:
for spec in specs[i].__sro__:
- comps = components.get(spec)
+ comps = cget(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 = cget(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):
+ cget = components.get # see _lookup above
if i < l:
for spec in reversed(specs[i].__sro__):
- comps = components.get(spec)
+ comps = cget(spec)
if comps:
_lookupAll(comps, specs, provided, result, i+1, l)
else:
for iface in reversed(provided):
- comps = components.get(iface)
+ comps = cget(iface)
if comps:
result.update(comps)
def _subscriptions(components, specs, provided, name, result, i, l):
+ cget = components.get # see _lookup above
if i < l:
for spec in reversed(specs[i].__sro__):
- comps = components.get(spec)
+ comps = cget(spec)
if comps:
_subscriptions(comps, specs, provided, name, result, i+1, l)
else:
for iface in reversed(provided):
- comps = components.get(iface)
+ comps = cget(iface)
if comps:
comps = comps.get(name)
if comps: