asyncio and blocking - an update

Frank Millman frank at chagford.com
Tue Feb 9 02:33:49 EST 2016


Hi all

Some of you may have been following my attempts to modify my asyncio app so 
that it does not block when accessing the database. Here is an update.

I came up with what felt like a good idea. Run the database handler in a 
separate thread, pass requests to it using a queue.Queue, and get it to pass 
results back using an asyncio.Queue.

It works, but I had a vague sense that performance was a bit sluggish, so I 
tried the 'recommended' approach of using asyncio.run_in_executor() to 
execute database calls in a separate thread. It felt a bit faster.

Now I have written a proper timing test, and the recommended approach is 
much faster. I am not 100% sure of the reason, but I think the problem is 
that, with my method, when the database tries to 'put' a row on the return 
queue, it has to use 'loop.call_soon_threadsafe()', and this seems to create 
a bottleneck.

It would not matter so much if I used cur.fetchall(), and sent all the rows 
back in one 'put', but I really wanted to iterate over the cursor and 'put' 
a row at a time. The idea was that it would be truly asynchronous from end 
to end - the database handler would retrieve rows one at a time, and via the 
queue my app would process them one at a time, all without blocking.

I can switch to fetchall(), but then there is no benefit over the 
recommended approach. Although fetchall() is non-blocking, once the rows are 
received as a list the function that processes them effectively does block. 
If that became a problem one could use an Asynchronous Iterator to process 
the list, but I have not had that need yet.

Writing timing tests is tricky. It is possible that under some 
circumstances, with a heavy load, a large table, and a time-consuming 
function to process each row, the overhead of call_soon_threadsafe() would 
be minimised and my approach might be effective. For now, however, I will 
regretfully abandon my approach and stick with run_in_executor().

Frank Millman





More information about the Python-list mailing list