0
votes

I have a python asyncio application, with several coroutines being run within a single thread. Some data is being passed using queues.

The queue consumer looks like this:

    async def queue_consumer(q):
        """Consume from an asyncio.Queue, making it an async iterable"""
        while True:
            try:
                e = await q.get()
                yield e
            except:
                continue

the consumer is being pulled from with async for. In this particular case the coroutine which consumes from a specific queue sequentially calls some code which puts data into its queue with put_nowait. EDIT: In this particular case coroutine A, which is listening for inbound network traffic, puts message into queue of coroutine B.

I have noticed that there is a consistent ~50ms delay between a call to put_nowait in coroutine A and then the data being processed as a result of pulling it from queue async iterable in coroutine B.

I suspect it might have something to do with some asyncio internal polling resolution, but I am not sure, not I would suspect where such configuration could be modified.

I would be very much interested in increasing event polling frequency in the asyncio loop, hence, decreasing observed delay between put_nowait and get to/from a queue between coroutines. Maybe also there's a way to hint asyncio framework to process items from the queue earlier?

NB: the application I am working with is not doing any computationally demanding work.

1
What happens between the put_nowait and the next await that actually yields back to the event loop?dirn
@dirn I have corrected the problem specification. Is your question still valid?Wojciech Migda
Can you reproduce this with a minimal example that we can run? E.g. just start two coroutines, print time.time() at the appropriate points, etc.user4815162342
Yes, my question is still valid. Unless the next line of code after put_nowait is something that yields control back to the loop (eg, await asyncio.sleep(0)), the coroutine that pulls from the queue may not even get a chance to check it for most of those 50ms.dirn
@dirn It turns out the problem was quite simple, and rather embarassing. I have learnt more about asyncio thanks to that, though. Please see my answer for details.Wojciech Migda

1 Answers

0
votes

It turns out the problem was caused by my app doing some UI updates with prompt_toolkit. I tracked this down by placing some measurements within _run_once. Anyway, the queue was not being processed because the event loop was busy executing some UI code that I did not expect to take so much time.