Multiple selectors in multiple threads Multiple selectors in multiple threads multithreading multithreading

Multiple selectors in multiple threads


No it is not beneficial, as the relation of code that needs to be processed vs. the time it takes for the IO operations is negligible. Especially if you consider the extra time you would need for the synchronization of fragmented data. It is however beneficial to have the processing of the received data done in separate threads.

So basically: have a single-threaded selector loop that copies the data from one buffer into a task-buffer for further processing in a separate thread, then launch a Runnable with that task-buffer in an Executor to process that copied data.


Is it beneficial to distribute incoming connections among n threads, each with its own independent NIO Selector, where n is, say, the number of cores in the server?

All major frameworks operate this way; Mina, Netty, Nginx, etc all distribute sockets across multiple selectors. Nginx literally passes the File Descriptor to a forked process having its own selector.

What you are describing here is the basic selector-worker model. You have usually 2 workers per core. Each worker has a Selector. This model is absolutely necessary on Windows as each Selector can only handle 1024 sockets and the work-around that the JDK does is catastrophic for performance.

http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b27/sun/nio/ch/WindowsSelectorImpl.java

  • Core 0 - Thread -> Selector -> OP_READ/OP_WRITE -> Do Business Logic
  • Core 1 - Thread -> Selector -> OP_READ/OP_WRITE -> Do Business Logic
  • Core 2 - Thread -> Selector -> OP_READ/OP_WRITE -> Do Business Logic
  • Core 3 - Thread -> Selector -> OP_READ/OP_WRITE -> Do Business Logic

This is the fundamental method of scaling the reactor pattern.

Its important that a single SocketChannel is only attached to a single Selector. So don't go calling SocketChannel.register() to a bunch of Selectors and listening to OP_READ on all of them because you won't gain any benefit.

http://man7.org/linux/man-pages/man7/epoll.7.html

Q2 Can two epoll instances wait for the same file descriptor? If so, are events reported to both epoll file descriptors?

A2 Yes, and events would be reported to both. However, careful programming may be needed to do this correctly.


This is exactly what Netty does. It uses N threads calling Selector.select() where N = (num available CPUs * 2) It is multiplied by 2 because of hyperthreading. This is the parent EventLoop which is considered the "acceptor eventloop" for accepting socket connections.Then there is the child EventLoop of thread workers

Suggest you have a look at NioEventLoopGroup-class