Slow performance when using HTTP get from within aiohttp application

1,870 views
Skip to first unread message

merr...@gmail.com

unread,
Jan 6, 2016, 2:15:40 AM1/6/16
to aio-libs
I have a very basic test application that gets the status of my Elasticsearch server:

async def handle(request):
    # blah = await aiohttp.get('http://localhost:9200')
    # await blah.release()
    return web.Response(body=b"Hello")

app = web.Application()
app.router.add_route('GET', '/', handle)
...

With the embedded aiohttp.get() commented out I get ~4500 reqs/sec ("wrk -t10 -c50 -d10s http://localhost:8080/")
With the HTTP GET uncommented, performance drops down to ~150 reqs/sec (ie 1/30th the performance)
The Elasticsearch status page is not a bottleneck as it cranks out ~60k reqs/sec ("wrk -t10 -c50 -d10s http://localhost:9200/")

This performance decrease seems surprising.  Am I doing something wrong?





Andrew Svetlov

unread,
Jan 6, 2016, 7:45:16 AM1/6/16
to aio-libs, merr...@gmail.com
You don't use benefits of connection pools and keep-alive connections.
Try out client session http://aiohttp.readthedocs.org/en/stable/client_reference.html#client-session but don't recreate it on every request -- keep session inside application's dictionary.

merr...@gmail.com

unread,
Jan 6, 2016, 11:45:40 AM1/6/16
to aio-libs, merr...@gmail.com
Thanks Andrew.  With the ClientSession, performance increased ~10x.  Can you elaborate on how I would keep the session inside the application's dictionary and access it through the handler (which is only passed the request)?  My current test code rather painfully accesses it as a global.

async def handle(request):
    resp = await client.get('http://localhost:9200')
    await resp.release()
    return web.Response(body=b"Hello")

app = web.Application()
app.router.add_route('GET', '/', handle)
client = aiohttp.ClientSession()

Andrew Svetlov

unread,
Jan 6, 2016, 2:04:49 PM1/6/16
to aio-libs, merr...@gmail.com


> On Wednesday, January 6, 2016 at 6:45:40 PM UTC+2, merr...@gmail.com wrote:
> Thanks Andrew. With the ClientSession, performance increased ~10x. Can you elaborate on how I would keep the session inside the application's dictionary and > access it through the handler (which is only passed the request)? My current test code rather painfully accesses it as a global.


async def handle(request):
    resp = await request.app['client'].get('http://localhost:9200')

    await resp.release()
    return web.Response(body=b"Hello")


app = web.Application()
app.router.add_route('GET', '/', handle)
app['client'] = aiohttp.ClientSession()
app.register_on_finish(app['client'].close)



merr...@gmail.com

unread,
Jan 6, 2016, 3:34:37 PM1/6/16
to aio-libs, merr...@gmail.com
Much appreciated!

Samuel Colvin

unread,
May 10, 2016, 1:29:00 PM5/10/16
to aio-libs, merr...@gmail.com
Slightly old thread I know, but I have a follow up question.

Is there a possibility that sessions could get very large in memory or slow down after a lot of requests? Eg. should I drop and recreate the session after 1000 or 10k requests?

Lastly does the session still make a difference to performance if the domains being requested from are all different? Eg. connection to numerous different servers.

Thanks
Reply all
Reply to author
Forward
0 new messages