I've done some simple tests and the IO subsystem (BIO vs NIO) makes little 
difference on a servers performance (when properly configured).  For example, I 
built a quick client and server to test NIO vs BIO performance.  It
was a simple echo server, only had 1 thread and the messages were
small, about 20 bytes if I recall.  I re-used the byte buffer to
absolutely minimize processing time.  The server was run on a 2ghz dual core
macbook pro.  The client was run from a couple of machines I have
around.  The macbook was the bottleneck.  My interest was finding the
absolute maximum messaging rate for a JVM.  I may have been able to increase 
the throughput by running a second thread so both cores would be put to use, 
but I didn't try that.



NIO in blocking mode with non-direct buffer:

    33,728 queries / sec


NIO in blocking mode with direct buffer:

    37,045 queries / sec



BIO:                                                                

    37,378 queries / sec



Thus, BIO has a very slight advantage but it's insignificant (0.8 % difference).

What does make a difference is the server architecture.  With blocking IO you 
should design your server as has been typically
done for some time - it's really the only choice.  The connection is
accepted and a thread-socket pair is used to process the request and
return the response.  If the server has to wait for the client at all the 
thread must block waiting for IO.  This presents a scalability problem because 
operating systems can only efficiently schedule a few hundred to at most a 
couple of thousand threads.  However, the server design is simple and there is 
no added IO latency as a result of the server design.  This is actually a very 
good design for many servers.  

The biggest advantage of NIO is it enables alternate server designs.  Typically 
with an NIO server you have a thread (or set of threads
- up to 1 per core recommended) performing your IO and other threads performing 
the "work" of your
application (since that may block).  This allows a server to support waiting on 
IO without tying up a thread per client.  So now a server can support a lot 
more clients with a lot fewer threads and thus it scales further.  The tradeoff 
however is higher latency because of the hand-off points between IO threads and 
worker threads.  You can use the NIO API to implement a traditional server 
design as well.  So the real difference in performance is the design of the 
server and not the IO API that is used (demonstrated by my micro-perf test 
above).

You have to choose between low latency with thread per client or slightly 
higher latency with higher thread efficiency.  You can't have both at the same 
time.  (But it would be interesting if you could switch dynamically between the 
two!  Unfortunately blocking is a channel wide setting so it would effect all 
connections and it probably cannot be safely changed once a channel is bound to 
a socket.)

So how do you choose between the two options?  You need to consider:

1) Incoming and outgoing message size.
2) Processing time.
3) Connection lifetime.

For systems that do not have long connection lifetimes, have a small message 
size and a short processing time the blocking IO _design_ is much better than 
the non-blocking IO _design_.  So for systems like typical DNS and most http 
1.0 servers blocking IO is probably a better choice.  For http 1.1, especially 
systems supporting AJAX w/ continuations non-blocking IO is much better because 
the connections are longer lived and the message size is much larger.  Of 
course there is a huge field of gray between those two extremes and you need to 
figure out which end of the spectrum your server is closer to. It sounds as 
though for your server Yann the BIO _design_ would be a better choice.

Fortunately, you can build both types of servers with mina (I believe).  If you 
want a blocking design you can either use one of Mina's blocking IO acceptors, 
or use the NIO acceptor but set it to blocking mode.  You would not have a 
worker thread pool and each connection would result in a new thread.  Perhaps 
you could use a thread pool for the acceptor, but I don't know if Mina 
currently supports that.  If you want the non-blocking design then you use Mina 
in the more traditional configuration of an acceptor and worker thread pool.

Something that would be very nice, and I will have a need for shortly, is to 
support both models in a single server instance (not dynamically switching 
though).  My server will be listening on multiple ports, X and Y.  Connections 
on port X will be short lived, small messages and minimal processing time.  
Thus, the BIO pattern is ideal.  Connections on port Y will be very long lived, 
but mostly idle connections.  So the NIO pattern would be best.  Connections to 
both ports will speak the same protocol and perform the same processing logic.  
Is this possible with Mina?  How would you configure the acceptors & pools?  
Code sample much appreciated.

UDPDatagramAcceptor(port x) --> single common processing instance
TCPDatagramAcceptor(port x) --> single common processing instance
TCPDatagramAcceptor(port y) -> WorkerThreadPool -> single common processing 
instance

Rob

----- Original Message ----
From: Vinod Panicker <[EMAIL PROTECTED]>
To: [email protected]
Sent: Thursday, April 5, 2007 6:12:24 AM
Subject: Re: Performances questions

On 4/5/07, yann Blazart <[EMAIL PROTECTED]> wrote:
> Hi thanks for your answer, but I 've tried to set the tcpNoDelay to false on
> each side and I didn't saw any really performance improvment.
> The first problem is that if I test by only sending message but not waiting
> for response, mina take 0.12 ms per call, aigainst Rmi that take 0.16 ms per
> call with the response. Is NIO slower than BIO, but more robust ?

I guess you can say that NIO is more efficient that BIO in most cases.
 Usually servers need to handle lots of concurrent connections and
that is where NIO really shines.  In your use case, if you have just a
single server and client and if there is no cpu starvation for the
threads, it is not at all surprising to see better performance from
BIO.  In fact, due to recent OS level improvements, using a
thread-per-connection model with BIO for a server seems to work pretty
well for quite a few use cases.

If your client and server are over the internet, do remember to factor
in I/O wait times that will occur if you use BIO.  If you can tell us
what your use case is, we can provide better suggestions.

HTH,
Vinod.






 
____________________________________________________________________________________
Need Mail bonding?
Go to the Yahoo! Mail Q&A for great tips from Yahoo! Answers users.
http://answers.yahoo.com/dir/?link=list&sid=396546091

Reply via email to