Le 7/12/12 11:21 AM, Lilinfeng a écrit :
Hi:
Hi !
Good afternoon.
I am a system designer at HUAWEI.
In recent 3 years, I have been using the Java NIO to develop high performance
service gate way,
Like SMS/MMS/WAP PUSH Gateway.
This year, I do the technology selection for the industry mature NIO framework,
such as Mina/Netty/NioFramwork/XSoket etc.
I found that Mina is the most outstanding architecture.
After reading the source code and performance test, I found there are some
optimization point.
Listed as follows:
The receiver buffer:
When we do reading operator, every time we create a new ByteBuffer for reading
bytes from SoketChannel, in long connection protocol,
Such as SMPP, frequently creating and destroy byte array will reduce the
performance. In fact , we can create a cache buffer in the session
As a attribute. After performance testing, this will improve performance over
20%(Long connect protocol).
This is not obvious. I mean, yes, possibily, when doing some specific
tests you will demonstrate that it can save some CPU, but on the other
hand, you may lose something else : for instance, keeping a ByteBuffer
in a cache means each session will keep a ByteBuffer, until the session
is closed. If you have tens of thousand sessions, with a 10k buffer for
instance, that means you'll keep 100Mb of memory allocated just for that
purpose. Not sure that it's sustainable in the long term.
I would say that we have to balance the advantage such a solution brings
with the drawbacks taht come with.
Decode half package(some Frames condition):
If the receive buffer is only a part of a message, we will use the
CumulativeProtocolDecoder class Solve it, we will cache the left buffer to
Session. If there are large number of half package scene, this will lead to
frequently creating and destroy byte buffer, this is not a best choice.
You can workaround this problem by using a different decoder. The
CumulativeProtocolDecoder is handy, as it does the job for you, but in
some cases, it's not efficient. In LDAP (ApacheDS project), we don't use
the CumulativeProtocolDecoder, we do process the bytes has they arrive,
and if the message is not complete, then we stop decoding until we get
some more bytes. We don't keep the ByteBuffer, we don't expand it, we
just construct the resulting message while decoding the bytes.
It's a bit more complex, but it gives excellent results.
In fact, before every looping, we mark the IoBuffer for record the first
package position, when the decode return false, we rest the IoBuffer to
The original position then return for receiving the next package. This will
reduce the times of IoBuffer creating and simple the process.
But you will have to copy the first part of the message somewhere in
memory. Likely in a byte[]. You are swapping the creation of a
ByteBuffer for the creation of a temporary storage...
I don't know which version of MINA you are using, nor the JVM version
you are running your test on, but one thing to recall is that with the
latest JVMs, creating an object is an extremelly cheap operation,
something probably cheaper than any other mechanism you may think of to
avoid creating such objects.
I'm not saying that to put down your ideas, some of them may be
interesting (I'm specifically thinking about caching *at least* a
limited size ByteBuffer withing every session, so that you spare the BB
creation for most of the received data), it's just that we have to
carefully evaluate the advantage we will get from applying them compared
to what we may lose on the other side...
Many thanks for those suggestions, and let's discuss them a bit further !
--
Regards,
Cordialement,
Emmanuel Lécharny
www.iktek.com