Skip to content

Commit

Permalink
iPerformace optimization in _lookup _lookupAll _subscriptions
Browse files Browse the repository at this point in the history
  • Loading branch information
jensens committed Feb 4, 2020
1 parent be82756 commit 8ab0194
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 6 deletions.
8 changes: 8 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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)
==================

Expand Down
19 changes: 13 additions & 6 deletions src/zope/interface/adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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:
Expand Down

0 comments on commit 8ab0194

Please sign in to comment.