libev-4.31 has just been released
Olivier Langlois
olivier at trillion01.com
Wed Apr 28 17:24:49 CEST 2021
Hi,
I just wanted to report back that my usage with libev iouring backend
appears to be working super fine.
It is a WebSocket client opening about 64 TCP connections.
The test has been performed with kernel 5.11.14.
By switching from epoll backend to io_uring one, my process CPU usage
did drop from 20-30% to below 5%. It seems too good to be true!
What I suspect happening is that my socket option SO_BUSY_POLL setting
might not be honored by io_uring.
Ultimately, what I am looking to improve is my application reaction
time. I might have more to say about io_uring effect on latency in 24h-
48h from now when I had the chance to collect some data.
I believe that in order to achieve the performance gain that io_uring
can deliver, you would need to service I/O through io_uring as well to
save on the associated system call cost instead of just using io_uring
for polling.
ie: currently, if data is available for reading for my 64 sockets and I
call read() 64 times from my libev io watcher callback. There is not
much performance gain here by using io_uring.
but if adding a function specific to libev io_uring backend that would
let the watcher code perform their i/o requests through io_uring was
thinkable, that could be the performance holy grail for libev users by
only making 1 system call to service the 64 i/o operations.
drawback of this optimization is that the watcher code couldn't be use
anymore with the other backends but that is the cost to pay to be able
to use a new API to its full potential...
I will probably end-up modifying my local copy of libev to play with
the idea. Let me know if there would be interest in knowing how my
experiment goes.
In the meantime, I took care of one of the TODO item. That is using a
single mmap() when possible. It is essentially code from liburing
adapted to libev coding style...
$ diff ev_iouring.c.orig ev_iouring.c
64c64
< * occur to him, and he made good on it by adding an unlimited
nuber
---
> * occur to him, and he made good on it by adding an unlimited
number
82c82
< /* TODO: take advantage of single mmap, NODROP etc. */
---
> /* TODO: take advantage of NODROP etc. */
323c323,324
< if (iouring_cq_ring != MAP_FAILED) munmap (iouring_cq_ring,
iouring_cq_ring_size);
---
> if (iouring_cq_ring != MAP_FAILED && iouring_cq_ring !=
iouring_sq_ring)
> munmap (iouring_cq_ring, iouring_cq_ring_size);
346c347
< if (!have_monotonic) /* cannot really happen, but what if11 */
---
> if (!have_monotonic) /* cannot really happen, but what if!! */
360c361
< if ((~params.features) & (IORING_FEAT_NODROP |
IORING_FEATURE_SINGLE_MMAP | IORING_FEAT_SUBMIT_STABLE))
---
> if ((~params.features) & (IORING_FEAT_NODROP |
IORING_FEAT_SUBMIT_STABLE))
380a382,388
> if (params.features & IORING_FEAT_SINGLE_MMAP)
> {
> if (iouring_cq_ring_size > iouring_sq_ring_size)
> iouring_sq_ring_size = iouring_cq_ring_size;
> iouring_cq_ring_size = iouring_sq_ring_size;
> }
>
383,384c391,395
< iouring_cq_ring = mmap (0, iouring_cq_ring_size, PROT_READ |
PROT_WRITE,
< MAP_SHARED | MAP_POPULATE, iouring_fd,
IORING_OFF_CQ_RING);
---
> if (params.features & IORING_FEAT_SINGLE_MMAP)
> iouring_cq_ring = iouring_sq_ring;
> else
> iouring_cq_ring = mmap (0, iouring_cq_ring_size, PROT_READ |
PROT_WRITE,
> MAP_SHARED | MAP_POPULATE, iouring_fd,
IORING_OFF_CQ_RING);
637c648
< /* we also clar the timeout if there are outstanding fdchanges */
---
> /* we also clear the timeout if there are outstanding fdchanges */
On Thu, 2020-03-19 at 09:34 +0100, Marc Lehmann wrote:
> > Currently, the io_uring interface evelopment in libev is on hold,
> > awaiting
>
> I might add, the iouring backend can be enabled in libev-4.33, and is
> expected to work. It has not really received testing, and it doesn't
> seem to
> have speed benefits yet.
>
> Anybody is invited to experiment with it - just don't use it in
> production.
>
More information about the libev
mailing list