diff options
author | Jens W. Klein <jk@kleinundpartner.at> | 2020-02-04 21:50:19 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-02-04 21:50:19 +0100 |
commit | 79be400cc9a5a8525db9e7869e401aede3d01d72 (patch) | |
tree | 52f5204db8a04d5959cb58baba0a89ee818730f7 | |
parent | be8275645900d3d598d59ef9644983a77ccc8f70 (diff) | |
parent | 1a7e4dc0c3e2bd4b1ece814efce7a34fbbf6efbf (diff) | |
download | zope-interface-79be400cc9a5a8525db9e7869e401aede3d01d72.tar.gz |
Merge pull request #167 from zopefoundation/lookup-performance
Performance optimization in _lookup _lookupAll and _subscriptions
-rw-r--r-- | CHANGES.rst | 8 | ||||
-rw-r--r-- | src/zope/interface/adapter.py | 19 |
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: |