Skip to content

Network

epoll

https://idndx.com/2014/09/01/the-implementation-of-epoll-1/

Old implementation with select or poll

With select or poll, the server handles all the requests by looking through the fd table, which is O(N) time.

A traditional echo server like TCP server, creates a thread/process for each client, block on read until the request finishes and write a response.

select and pollsystem call

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

select allow a program to monitor multiple file descriptors, waiting until one or more of the file descriptors become "ready" for some class of I/O operation (e.g., input possible). A file descriptor is considered ready if it is possible to perform the corresponding I/O operation without blocking.

int poll (struct pollfd *fds, unsigned int nfds, int timeout);

struct pollfd {
      int fd;
      short events; 
      short revents;
};

poll use pollfd which has a different fields for the events and the returning events. It checks the bits in revents which represents the events that actually occurred, and events represents the events that we are actually interested in.

The time complexity is the same, but poll has less fields to specify. e.g, no number of fd needs to be specified.

epoll system call

epoll is not part of POSIX, but supported by linux. It is much more efficient if there are many file descriptors.

Three steps from guide

  • epoll_create() : create a context
  • epoll_ctl() : add monitored fds and related data structure to the context
  • epoll_wait() : does the actual wait, return a file descriptor that satisfies the events.

The time complexity of monitoring is O(1), also less context switching between user space and kernel space - the context created is always within kernel space. Less CPU time was spent on finding available fds.

  • epoll source code analysis here