poll(2) slower than select(2)

I have a program that creates a TCP server socket and listens on it.

When the program accepts a connection from a client, it calls poll(2) repeatedly to see if there is any input available, like this:

for (int i = 0; i < 1000000; i++) {
  struct pollfd fds[] = {{ .fd = clientfd, .events = POLLIN, .revents = 0 }};
  int r = poll(fds, 1, 0);
  if (r < 0) {
    perror("poll");
    exit(1);
  }
}    

On my Intel iMac, this takes about 15 seconds. If I use select(2) instead, as follows, it takes about 550ms.

for (int i = 0; i < 1000000; i++) {
  struct timeval timeout = { .tv_sec = 0, .tv_usec = 0 };
  fd_set infds;
  FD_ZERO(&infds);
  FD_SET(clientfd, &infds);
  int r = select(1, &infds, 0, 0, &timeout);
  if (r < 0) {
    perror("select");
    exit(1);
  }
}

https://gist.github.com/xrme/cd42d3d753ac00861e439e012366f2cf is a C source file that contains a complete example.

If you're inclined to take a look, please download the file from the gist and do cc poll-test.c and then ./a.out. Connect to it with nc 127.0.0.1 6444 and observe that it will take quite a while. (Activity Monitor will show a large number of "idle wake ups", but I'm not clear what that signifies.)

Recompile with cc -DUSE_SELECT, run ./a.out and connect again, and it will complete in under a second.

Advisability of this usage aside (which is adapted from a much larger system), is there anything here to be done to make poll faster? Other systems I have looked at (FreeBSD, OmniOS, Linux) do not exhibit the same slowdown with poll.

macOS, with its BSD heritage, has always treated poll as a bit of compatibility interface. Still, the result you’re seeing is quite surprising, and I encourage you to file a bug about that. Please post your bug number, just for the record.

However, this is a very unrealistic microbenchmark. Most networking code doesn’t call poll in a tight loop with a zero timeout. Moreover, the semantics of poll, and select for that matter, are really quite bad. You’re likely to see much better results with kqueues.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I made FB15286484 about this issue.

Thank you for your reply.

poll(2) slower than select(2)
 
 
Q