Java Reference
In-Depth Information
quires about one extra megabyte of RAM. On a large server that may be processing
thousands of requests a second, you may not want to assign a thread to each connection.
It's faster if one thread can take responsibility for multiple connections, pick one that's
ready to receive data, fill it with as much data as that connection can manage as quickly
as possible, then move on to the next ready connection.
To work well, this approach needs to be supported by the underlying operating system.
Fortunately, pretty much every modern operating system you're likely to be using as a
high-volume server supports such nonblocking I/O. However, it might not be well sup‐
ported on some client systems of interest, such as tablets, cell phones, and the like.
Indeed, the java.nio package that provides this support is not part of any current or
planned Java ME profiles, though it is found in Android. However, the whole new I/O
API is designed for and only really matters on servers, which is why I haven't done more
than allude to it until we began talking about servers. Client and even peer-to-peer
systems rarely need to process so many simultaneous connections that multithreaded,
stream-based I/O becomes a noticeable bottleneck.
NIO Too Little, Too Late?
There was a time when properly architected nonblocking I/O dramatically outper‐
formed multithreaded, multiprocess designs. That time was the 1990s. Unfortunately,
Java didn't get nonblocking I/O until Java 1.4 in 2002. By the time Java 5 was released
in 2004 and certainly by the time Java 6 was released in 2006, the continuing improve‐
ments to native threading in operating systems had eliminated almost all context
switching and uncontested synchronization overhead. Furthermore, server memory
had grown to the point where 10,000 simultaneous threads could easily fit in memory
on commodity hardware; and multicore/multi-CPU systems that required multiple
threads for maximum utilization were becoming common. On today's Java 7 and Java
8 64-bit VMs that's even more true. In 2013, it's really hard to justify the added com‐
plexity of a NIO-based architecture compared to a much simpler thread-per-request or
thread-per-connection design.
But isn't NIO faster? Not necessarily. In actual measurements in Java 6 on Linux , multi-
threaded classic I/O designs outperform NIO by 30% or so.
Are there any situations in which asynchronous I/O does beat classic I/O? Maybe. The
one situation I can still imagine is a server that needs to support a colossal number of
long-lived, simultaneous connections, say 10,000+, but where each client doesn't send
very much data very frequently. For instance, imagine a central server in the home office
collecting transactions from each cash register in a nationwide chain of convenience
stores. This scenario is tailor-made for NIO, and can probably be implemented much
more efficiently with asynchronous or nonblocking on-demand processing in just a few
threads.
But always remember the two golden rules of optimization:
 
Search WWH ::




Custom Search