dev@grizzly.java.net

Re: NIO vs IO

From: charlie hunt <charlie.hunt_at_oracle.com>
Date: Thu, 29 Jul 2010 08:14:52 -0500

Emmanuel Lécharny wrote:
> On 7/29/10 11:18 AM, Oleksiy Stashok wrote:
>> Yeah, I read similar articles before.
>>
>>> A bit dated, but still interesting read even though my experiments
>>> don't support these claims:
>>> http://www.thebuzzmedia.com/java-io-faster-than-nio-old-is-new-again/
>>>
>>> The biggest omission I found was that the claims are based on the
>>> assumption that the clients are really fast. But as we know, in
>>> reality this is usually not the case.
>> IMO it doesn't depend much on how fast clients are, may be indirectly.
>> As I understood the main point was that modern OSes have very
>> optimized thread and memory management. So big amount of idle
>> threads, which have some context associated and wait for blocking I/O
>> operations to complete, have minimal impact on the active threads.
>> And idle<->active thread state switch (with all its context) is not
>> so expensive operation.
> One important think to remember is that the number of threads a JVM
> can handle is 16 000. When using a NIO based application, you may
> exceed this number when dealing with hundred of thousands sessions.
> Either Grizzly, MINA or Netty3 have already faced such constraints,
> and I don't see how possibly you can use a plain IO solution in this
> case.
Just a small clarification ... the number of threads a modern JVM can
support is not necessarily limited to 16,000 threads. It's more a
function of the address space consumed by a Java thread and the amount
of addressable space available to the JVM process along with the address
space consumed by other artifacts of the JVM.
>
>> For me It could be interesting to see the benchmark comparison for
>> some real-life scenario, let's say web/app server.
> What would be *very* interesting is to see how a plain IO server
> behaves when reaching the limit (ie with 16 000 connected clients),
> compared to a NIO based app. That includes the memory consumption, not
> only the CPU.
I think that's the real key ... i.e. for a relatively small number of
connections, I find it no surprise to hear plain ol' IO performs better
than NIO. It's quite a different story with a large number of
connections. With non-blocking NIO with a Selector thread you will get
thread context switching in addition to having a couple system calls to
enable & disable interest ops on the SelectionKey. Frequent thread
context switching and frequent system calls can waste a large number of
CPU cycles. Nailing a connection to a socket can elide those issues.
But, for a large number of connections, that model will run into issues.

Given modern CPUs have larger number of cores and hardware threads along
with JVMs showing better scalability with 64-bit JVMs w/ compressed
references moves the threshold at which the 1-to-1 connection to thread
mapping higher to where the NIO Selector starts to show better performance.

All this being said, for many applications with a small number of (busy
or bursty) connections, a non-blocking SocketChannel with a dedicated
Selector, could very well outperform the traditional java.net.Socket
approach since a non-blocking SocketChannel can be implemented to read
as much data as there is available which can reduce the number of system
calls used.

One last comment ... the use of a Selector to receive indications that
there is something ready to be read or written has a more significant
cost on Windows than it does on Linux or Solaris, (or Mac OS X). So,
if the tests were run on Windows, the penalty associated with using the
NIO Selector relative to the java.net.Socket approach is going to be
higher which means the # of connections threshold at which the NIO
Selector yields better performance will likely be higher than it is for
Linux or Solaris.

charlie ...