Submit #3135


Added by tautolog 11 months ago.

Target version:
Start date:
Due date:
% Done:


Estimated time:


This isn't complete yet, as I need to add entries in the manual, and I would like to add some more filtering code for listen sockets, and some other types of files. But I wanted to show this theory, and get feedback.

I spend a lot of time trying to optimize network event loops. What I end up doing is writing code that speculates on the state of the socket buffers. Level-triggering works okay for reading for some time, but if the protocol handler gets blocked, it needs to deregister or get itself into an event spin, so there ends up being a lot of de-registering and re-registering in a sophisticated platform. So then EV_ONESHOT can be used, or EV_DISPATCH with EV_ENABLE, which basically gives you edge-triggering, but then you need to register all the time. Luckily, kqueue allows you to batch these registrations, so the overhead isn't so bad, but it requires adding codepaths that aren't required in linux. So, I came up with something that I think is even better, after looking at how to add edge-triggering into kqueue.

kqueue has the data field that reports the socket availability in bytes. The issue with level-triggering is that the userland side only needs to be made aware of changes to that state. I realized that a more optimal interface would be for the userland to register once for each side of the connection, and then the kernel gives a single update per change to any of the socket state. Then the application can merely store the latest kevent struct on its connection struct, and always have the latest information that the kernel has on the state of the socket buffers. Then, sophisticated optimizations become straightforward. See the example echo network server in kqsbtest.c.

dfly_evfilt_recv.patch (5.83 KB) dfly_evfilt_recv.patch tautolog, 05/25/2018 09:48 PM
kqsbtest.c (8.8 KB) kqsbtest.c tautolog, 05/25/2018 09:49 PM

Also available in: Atom PDF