On Mon, May 14, 2007, guy keren wrote about "Re: need some help with tcp/ip 
programming":
> >this is interesting. can anyone provide more info on this?
> the problem with select, is that it is unable to optimize handling of 
> 'holes' in the file descriptor set.
> suppose that you need to select on file descriptors 2 and 4000.
> you need to pass info about all file descriptors up to 4000 (i.e. many 
> '0' bits, and only two '1' bits, in the different select sets).
> with poll, you pass an array of the descriptors you care about. so the 
> size of the array is proportional to the amount of descriptors you are 
> interested in, while with select it is proportional to the numeric value 
> of the largest descriptor you are interested in.

This is indeed an accurate accessment of the difference between pol and
select. Another point worth noticing is that in select(), the same array
is used both as input and output. This means that after every event, you
need to refill this array, which can be quite slow if you have many thousands
of events per second.

In some cases, you reach a point where you are listening to thousands
of file descriptors, and getting thousands of events per second. For example,
one can write a single-threaded HTTP server which handles thousands of
concurrent connections with amazing performance (I wrote such a server
once, and it was a really interesting experience). When you reach such
high demands, even poll() is not good enough - every time one fd is ready
to act on, something which can happen thousands of times per second - you
need to call the poll() system call again, and pass to the long array of
fds from userspace to the kernel. The problem is that the time poll()
takes is proportional to the number of fds to poll, rather than to the
number of fds in which something actually happened.

To solve this problem, the "/dev/epoll" interface was added to Linux in
2001, and later, apparently because Linus Torvalds doesn't like /dev
tricks, new system calls were added instead (see epoll(4))).

It was amazing to see a system on which Apache stuggled to keep 200
concurrent open connections, suddenly keep thousands of concurrent
open connections, using only one thread (or N threads in a machine
with N cpus). Together with sendfile(), this allows you to create
killer Web servers :-)

> when you use poll, you can use the trick of having 2 theads - one polls 
> on "idle" sockets (i.e. sockets that did not have I/O in the last X 
> seconds), and one listens on 'active' sockets (i.e. sockets that had I/O 
> in the last X seconds). this avoids the major problem with both select 
> and poll - that after an event on a single socket, the info for all the 
> sockets has to be copied to user space (when select/poll returns), and 
> then to kernel space again (when invoking poll/select again).
> 
> i think that people added epoll support in order to avoid waking the 
> poll function altogether - by receiving a signal form the kernel with 
> the exact info, instead of having to return from poll.

Indeed (see my above explanation). epoll() *does* return from the poll
every time, but it immediately lets you know what changed (no need to
check a long array), and more importantly - when you want to call epoll()
again there is no need to pass the long list of fds to the kernel again.

-- 
Nadav Har'El                        |      Tuesday, May 15 2007, 27 Iyyar 5767
[EMAIL PROTECTED]             |-----------------------------------------
Phone +972-523-790466, ICQ 13349191 |Ms Piggy's last words: "I'm pink,
http://nadav.harel.org.il           |therefore I'm ham."

=================================================================
To unsubscribe, send mail to [EMAIL PROTECTED] with
the word "unsubscribe" in the message body, e.g., run the command
echo unsubscribe | mail [EMAIL PROTECTED]

Reply via email to