I have worked on servers that had this problem with select(2). poll was better but kqueue was much much better (from near-100% utilization with a few thousand open fds to < 1% cpu utilization; please forgive the vague numbers, it was 7 years ago at a company that I no longer work for).<p>If you're using nonblocking I/O, or threads, select can become the bottleneck with a few thousand interesting connections at sizes that are much less than the FD_SETSIZE max.<p>The user-space CPU utilization should be near-0 since this is really a kernel I/O problem; the fact that it is much higher is an indication that a lot of wasted user space work is being done.<p>Select, by design, has a flaw: the kernel must scan the bitmask for the highest-numbered fd passed in, even if there is little change in the fd_set bitmask (as is usually the case). This means incurring a cost if any fd in the set has a high fd number. The fd on which you accept probably has a low number, but your client I/O fds will have increasing numbers as the server gets greater and greater utilization.<p>kqueue (and epoll, but I haven't used it) resolve this problem nicely. Only things that change state must be communicated. poll is better than select in this respect if the array is sparse, but if a large number of fds are interesting, it will also get expensive.