Hi, I've a "strange" behaviour with AsyncIO: more I try to improve the performances, more it's slow. I certainly missed something in AsyncIO, or maybe you have some tips other than try and benchmark for each change.
For example, this is two coroutines to update data from PostgreSQL, executed by aiohttp.web and API-Hour: (If you want to see all code, it's available here: https://github.com/Eyepea/FrameworkBenchmarks/tree/API-Hour/frameworks/Python/API-Hour/hello/hello ) @asyncio.coroutine def update_random_records(container, limit): results = [] for i in range(limit): results.append((yield from update_random_record(container))) return results @asyncio.coroutine def update_random_record(container): pg = yield from container.engines['pg'] world = yield from get_random_record(container) with (yield from pg.cursor()) as cur: yield from cur.execute('UPDATE world SET randomnumber=%(random_number)s WHERE id=%(idx)s', {'random_number': randint(1, 10000), 'idx': world['Id']}) return world When I launch wrk (HTTP benchmark tool) on HTTP server, I've this result: lg@steroids:~$ wrk -t8 -c256 -d30s http://127.0.0.1:8008/updates?queries=20 Running 30s test @ http://127.0.0.1:8008/updates?queries=20 8 threads and 256 connections Thread Stats Avg Stdev Max +/- Stdev Latency 547.86ms 428.03ms 2.90s 85.37% Req/Sec 59.53 12.62 92.00 69.32% 14283 requests in 30.04s, 10.99MB read Socket errors: connect 0, read 0, write 0, timeout 37 Requests/sec: 475.42 Transfer/sec: 374.46KB Now, when I try to change coroutine update_random_records to launch all update_random_record coroutines in the same time instead to wait the end of update_random_record to launch a new coroutine: @asyncio.coroutine def update_random_records(container, limit): tasks = [] results = [] for i in range(limit): tasks.append(container.loop.create_task(update_random_record(container))) yield from asyncio.wait(tasks) for task in tasks: results.append(task.result()) return results I've this result: lg@steroids:~$ wrk -t8 -c256 -d30s http://127.0.0.1:8008/updates?queries=20 Running 30s test @ http://127.0.0.1:8008/updates?queries=20 8 threads and 256 connections Thread Stats Avg Stdev Max +/- Stdev Latency 585.21ms 563.88ms 3.95s 89.03% Req/Sec 57.56 18.82 118.00 66.89% 13480 requests in 30.04s, 10.37MB read Socket errors: connect 0, read 0, write 0, timeout 193 Requests/sec: 448.76 Transfer/sec: 353.49KB As you can see, less requests/sec but also more HTTP requests in timeout. The limitation should be my PostgreSQL database. And now, if I add a Semaphore(value=10) to reduce concurrent coroutines of update_random_records : @asyncio.coroutine def update_random_record(container): with (yield from container.semaphores['updates']): pg = yield from container.engines['pg'] world = yield from get_random_record(container) with (yield from pg.cursor()) as cur: yield from cur.execute('UPDATE world SET randomnumber=%(random_number)s WHERE id=%(idx)s', {'random_number': randint(1, 10000), 'idx': world['Id']}) return world Now: lg@steroids:~$ wrk -t8 -c256 -d30s http://127.0.0.1:8008/updates?queries=20 Running 30s test @ http://127.0.0.1:8008/updates?queries=20 8 threads and 256 connections Thread Stats Avg Stdev Max +/- Stdev Latency 619.24ms 476.83ms 3.20s 81.59% Req/Sec 52.74 9.49 81.00 69.92% 12590 requests in 30.03s, 9.68MB read Socket errors: connect 0, read 0, write 0, timeout 53 Requests/sec: 419.23 Transfer/sec: 330.21KB It's better, but less rapid than the first attempt with a simple yield form in a loop. Change Semaphore value doesn't change the result a lot. I'd already have this problem with AsyncIO in another context, slurp all databases content of a CouchDB instance: When I've tried to launch several I/O HTTP requests in same time, Python script had needed more time. It could be the context switching between coroutines that reduces performance ? How to identify/measure that ? Thanks for your ideas. Regards.
