pycapnp
pycapnp copied to clipboard
RPC throughput slow due to poll sleep
pycapnp
is based on polling and generally sleeps for 0.01
second between polls. This means that a maximum of 100 messages per second can be exchanged. This is a significant slow-down. By decreasing the sleeping time, I can get a throughput in the order of 10000 messages per second. So at least I would suggest decreasing the sleeping time. But this comes at the cost of higher idle cpu.
Is there any way of using the library in a blocking style without relying on polling?
Yeah, I agree this is a problem.
The tricky part is that two async systems (kj and asyncio) have to talk to each other. I believe this is possible but I haven't been able to figure out a better way (so far). Effectively asyncio needs a way to be told "an event happened, process it".
KJ's event loop APIs are designed to be able to stack on top of other event loops. It's not easy, but it's possible. I did it for Node.js's libuv here (first 654 lines of the file): https://github.com/capnproto/node-capnp/blob/node10/src/node-capnp/capnp.cc
I'd love to resolve this issue somehow. Can either of you suggest a reasonable way of performing the stacking of the event loops? I'm having trouble matching the implementation @kentonv did for node.js and how that would transfer to pycapnp.
I stumbled upon this issue when checking why an async application based on pycapnp results in about 5-10% persistent CPU usage on a Raspberry Pi. Although the former is no deal-breaker for us, the performance implications resulting from the polling mechanism definitely are.
I am not familiar with the implementation details of Cap'nProto and KJ, but would it be an option to address this issue by doing a synchronous wait in another thread and handing the data via an awaitable pipe or queue to the main thread? (I also thought about an asyncio.Future
triggered via loop.call_soon_threadsafe
, but this would probably require spawning a new thread for each read
and a_wait
invocation.)
I haven't dug too deep into this, but this might provide some hints https://stackoverflow.com/questions/51029111/python-how-to-implement-a-c-function-as-awaitable-coroutine and https://stackoverflow.com/a/54675255
The main thing is to give enough to the python asyncio api such that we don't need to poll.