front | blog | talks | docs | photos | contact | about
Related: All docs, FTP vs HTTP, bittorrent vs HTTP and curl vs Wget

poll vs select vs event-based

I failed to find a thorough comparison page on poll() vs select() so I wrote my own. If you find flaws or have additions, please let me know! My blog post also provides some background.

Differences between poll() and select() and to the end some mentions about the more modern event-driven alternatives such as epoll(), kqueue and more. I recommend a library such as libev or libevent.

Those libs make it possible to write event-based programs in a portable manner, as the underlying technologies like epoll (Linux), kqueue (FreeBSD, NetBSD, OpenBSD, Darwin) and /dev/poll (Solaris, HPUX), pollset (AIX), Event Completion (Solaris 10) are different between platforms and aren't standardized. The Windows solution seems to be I/O Completion Ports


select() was introduced in 4.2BSD Unix, released in August 1983.

poll() was introduced in SVR3 Unix, released 1986. In Linux, the poll() system call was introduced in 2.1.23 (January 1997) while the poll() library call was introduced in libc 5.4.28 (May 1997)


select() and poll() provide basically the same functionality. They only differ in the details:

Going with an event-based function instead should provide the same functionality as well. They do however often force you to use a different approach since they're often callback-based that get triggered by events, instead of the loop style approach select and poll encourage.


poll and select are basically the same speed-wise: slow.

Going with an event-based function is the only sane option if you go beyond a small number of file descriptors. The libev guys did a benchmarking of libevent against libev and their results say clearly that libev is the faster one.

Compared to poll and select, any event-based system will give a performance boost already with a few hundred file descriptors and then the benefit just grows the more connections you add.


select - has existed for a great while and exists almost everywhere. A problem with many file descriptors is that you cannot know if you will overflow the the bitmask as you can't check the file descriptor againt FD_SETSIZE in a portable manner.

Many unix versions allow FD_SETSIZE to be re-defined at compile time, but Linux does not

One quirk is that the include header required for the fd_set type varies between systems.

Some - but not all - systems modify the timeout struct so that on return from select, the program can know how long time actually passed. If you repeat select() calls, you need to init the timeout struct each loop!

poll - Not existing on older unixes nor in Windows before Vista. Broken implementation in Mac OS X at least up to 10.4 and earlier. Up to 10.3 you could check for a poll() that works with all arguments zeroed. The 10.4 bug is more obscure an I don't know of any way to detect it without checking for OS.

Lots of early implementations did poll as a wrapper around select().

poll's set of bits to return is fairly specific in the standards, but vary a lot between implementations


All event-driven functions tend to make the code more complex, harder to follow and require more code to be written to accomplish the same task as the simple select and poll approaches do.

More Reading

For everyhing select/poll/event-based, there's the C10K problem page, which is a true goldmine.

For great benchmarks on network scalability on a few operating systems, see Felix von Leitner's work.

Thanks To

The following friends helped me improve this text by pointing out flaws or enhancements: Fabian Keil

Updated: December 10, 2018 15:15 (Central European, Stockholm Sweden)