Skip to content

Commit

Permalink
Skip middleware code when there are no user middlewares installed (#2629
Browse files Browse the repository at this point in the history
)

* Skip middleware code when there are no user middlewares installed

Fixes performance issue introduced by #2577, boosting from 8K req/sec
to almost 9K req/sec.

If there are no middlewares installed by the user the attribute
`request._match_info.current_app` already looks at to the right app,
this is by design.
  • Loading branch information
pfreixes authored Dec 28, 2017
1 parent 16e7d1b commit af3cb34
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 7 deletions.
1 change: 1 addition & 0 deletions CHANGES/2629.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixes performance issue introduced by #2577. When there are no middlewares installed by the user, no additional and useless code is executed.
27 changes: 20 additions & 7 deletions aiohttp/web_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,15 +110,25 @@ def freeze(self):
return

self._frozen = True
self._middlewares = tuple(self._prepare_middleware())
self._middlewares.freeze()
self._router.freeze()
self._on_response_prepare.freeze()
self._on_startup.freeze()
self._on_shutdown.freeze()
self._on_cleanup.freeze()
self._middlewares_handlers = tuple(self._prepare_middleware())

# If current app and any subapp do not have middlewares avoid run all
# of the code footprint that it implies, which have a middleware
# hardcoded per app that sets up the current_app attribute. If no
# middlewares are configured the handler will receive the proper
# current_app without needing all of this code.
self._run_middlewares = True if self.middlewares else False

for subapp in self._subapps:
subapp.freeze()
self._run_middlewares =\
self._run_middlewares or subapp._run_middlewares

@property
def debug(self):
Expand Down Expand Up @@ -241,6 +251,7 @@ def _prepare_middleware(self):
'see #2252'.format(m),
DeprecationWarning, stacklevel=2)
yield m, False

yield _fix_request_current_app(self), True

async def _handle(self, request):
Expand All @@ -260,12 +271,14 @@ async def _handle(self, request):

if resp is None:
handler = match_info.handler
for app in match_info.apps[::-1]:
for m, new_style in app._middlewares:
if new_style:
handler = partial(m, handler=handler)
else:
handler = await m(app, handler)

if self._run_middlewares:
for app in match_info.apps[::-1]:
for m, new_style in app._middlewares_handlers:
if new_style:
handler = partial(m, handler=handler)
else:
handler = await m(app, handler)

resp = await handler(request)

Expand Down
26 changes: 26 additions & 0 deletions tests/test_web_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ def test_app_delitem():
def test_app_freeze():
app = web.Application()
subapp = mock.Mock()
subapp._middlewares = ()
app._subapps.append(subapp)

app.freeze()
Expand All @@ -210,3 +211,28 @@ def test_equality():

assert app1 == app1
assert app1 != app2


def test_app_run_middlewares():

root = web.Application()
sub = web.Application()
root.add_subapp('/sub', sub)
root.freeze()
assert root._run_middlewares is False

@web.middleware
async def middleware(request, handler):
return await handler(request)

root = web.Application(middlewares=[middleware])
sub = web.Application()
root.add_subapp('/sub', sub)
root.freeze()
assert root._run_middlewares is True

root = web.Application()
sub = web.Application(middlewares=[middleware])
root.add_subapp('/sub', sub)
root.freeze()
assert root._run_middlewares is True

0 comments on commit af3cb34

Please sign in to comment.