Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Concurrency with aiohttp server

Here is my code:

import asyncio
import logging
import time

from aiohttp import web

logging.getLogger('aiohttp').setLevel(logging.DEBUG)
logging.getLogger('aiohttp').addHandler(logging.StreamHandler(sys.stderr))

def handle_sync(request):
    web.web_logger.debug('Sync begin')
    time.sleep(10)
    web.web_logger.debug('Sync end')
    return web.Response(text='Synchronous hello')


async def handle_async(request):
    web.web_logger.debug('Async begin')
    await asyncio.sleep(10)
    web.web_logger.debug('Async end')
    return web.Response(text='Asynchronous hello')


async def init(loop):
    app = web.Application(loop=loop)
    app.router.add_get('/sync/', handle_sync)
    app.router.add_get('/async/', handle_async)

    srv = await loop.create_server(app.make_handler(), '0.0.0.0', 8080)
    return srv

loop = asyncio.get_event_loop()
loop.run_until_complete(init(loop))
loop.run_forever()

I would expect 2 behaviors:

  • when hitting twice the /sync/ url, with let's say a 2-seconds interval, the overall time spent is 20 seconds since we have one server in one thread, and a blocking call
  • an overall time of 12 seconds when hitting twice the /async/ url the same way (these calls are asynchronous, right?)

But it appears that both cases last 20 seconds, can someone please explain me why?

like image 767
Emmanuel Avatar asked Nov 16 '25 22:11

Emmanuel


1 Answers

To be able to observe the benefits using async here, you will need to send the two separate request at (almost) the same time.

The await call simply means the function yields control over to the event loop so that if any other events occur, they can be handled without blocking. If you do send two requests at the same time to the async endpoint, you will see that each of them finishes around 10 seconds. This is because both requests are handled at the same time: the first request does not block the server from handling another request.

However if you send two requests in a similar fashion to the sync endpoint, the second request would take 20 seconds. This is because the sync endpoint blocks on the first request and can not start serving the second request until the first one is finished.

like image 112
bow Avatar answered Nov 19 '25 13:11

bow