Wikipedia says
unlike the older system calls, which operate at O(n), epoll operates in O(1) [2]).
http://en.wikipedia.org/wiki/Epoll
However, the source code at fs/eventpoll.c on Linux-2.6.38, seems it is implemented with an RB tree for searching, which has O(logN)
/* * Search the file inside the eventpoll tree. The RB tree operations * are protected by the "mtx" mutex, and ep_find() must be called with * "mtx" held. */ static struct epitem *ep_find(struct eventpoll *ep, struct file *file, int fd) {
In fact, I couldn't see any man page saying the complexity of epoll() is O(1). Why is it known as O(1)?
epoll is a Linux kernel system call for a scalable I/O event notification mechanism, first introduced in version 2.5. 44 of the Linux kernel. Its function is to monitor multiple file descriptors to see whether I/O is possible on any of them.
epoll stands for event poll and is a Linux specific construct. It allows for a process to monitor multiple file descriptors and get notifications when I/O is possible on them. It allows for both edge-triggered as well as level-triggered notifications.
performance: select & poll vs epoll So using epoll really is a lot faster once you have more than 10 or so file descriptors to monitor.
epoll_ctl() is a control function that allows us to add descriptors to a watch set, remove descriptors from a watch set, or reconfigure file descriptors already in the watch set. epoll_wait() waits for I/O events on the watch set, blocking the calling thread until one or more events are detected.
This makes sense once you look for ep_find
. I only spent a few minutes with it and I see ep_find
is only called by epoll_ctl
.
So indeed, when you add the descriptors (EPOLL_CTL_ADD
) that costly operation is performed. BUT when doing the real work (epoll_wait
) it isn't. You only add the descriptors in the beginning.
In conclusion, it's not enough to ask the complexity of epoll
, since there is no epoll
system call. You want the individual complexities of epoll_ctl
, epoll_wait
etc.
There are other reasons to avoid select
and use epoll
. When using select, you don't know how many descriptors need attention. So you must keep track of the biggest and loop to it.
rc = select(...); /* check rc */ for (s = 0; s <= maxfd; s++) { if (FD_ISSET(s)) { /* ... */ } }
Now with epoll
it's a lot cleaner:
nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1); /* check nfds */ for (n = 0; n < nfds; ++n) { /* events[n].data.fd needs attention */ }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With