|
Home > Archive > Apache Directory Project > April 2006 > ByteBuffer usage, performance, leak
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
ByteBuffer usage, performance, leak
|
|
| Colin Cullen 2006-04-17, 11:57 pm |
| Hi,
I am seeking some help regarding Mina. I have completed development of a
server using Mina 0.8.2. This server will be providing financial deal
ticket information to multiple clients. Functionally everything works great
but I do seem to have a memory leak and slowly degrading performance. I am
testing using a single production level client (not Mina based). The server
protocol sends a deal ticket down to the client and then awaits a high level
acknowledgement from the client indicating whether the ticket has passed or
failed client side validation. The performance degradation occurs between
the writing of the message object (deal ticket) at the protocol level and
the reception of the response message in its message handler. BTW I am
using Mina's DemuxingProtocolCodecFactory and DemuxingProtocolHandler to
model the server and provide the codec/handler glue. I am concerned about
whether I am using Mina's ByteBuffer properly. I have also read on the
board that Mina will automatically place an allocated ByteBuffer in its
ByteBuffer pool.
My output buffer requirements are pretty minimal. The deal ticket message
is around 1K bytes. I allocate a single ByteBuffer for each session and
keep it in the session object, which is stored in Mina's session context
map, when a deal ticket needs to be written to the client the pre-allocated
ByteBuffer is retrieved from the session context object and used for
building the outbound data set. Here are the actual code fragments:
This factory creates a session context object for each connection:
public class SessionContextFactory
{
static private SessionContextFactory instance = new
SessionContextFactory();
static public SessionContextFactory getInstance()
{
return SessionContextFactory.instance;
}
private SessionContextFactory()
{
}
public SessionContext createSessionContext(ProtocolSession session)
{
return new SessionContext(session);
}
public final class SessionContext implements SessionContext,
LifeSpanControllable
{
ByteBuffer dataBuffer;
private SessionContext(ProtocolSession session)
{
dataBuffer = ByteBuffer.allocate(1024);
}
public ByteBuffer getDataBuffer()
{
dataBuffer.acquire();'
return dataBuffer;
}
}
}
This class performs the message encoding using the single ByteBuffer
retrieved from the session context object:
public abstract class EasiAbstractMessageEncoder implements MessageEncoder
{
private final String type;
protected EasiAbstractMessageEncoder(String type)
{
this.type = type;
}
protected String getType()
{
return type;
}
public void encode(ProtocolSession session, Object message,
ProtocolEncoderOutput out) throws ProtocolViolationException
{
SessionContext sessCtx =
(SessionContext)session.getAttribute(ServerConstants.SESSION_CONTEXT);
EasiAbstractMessage m = (EasiAbstractMessage)message;
ByteBuffer buf = sessCtx.getDataBuffer();
buf.clear();
// Encode the header
encodeHeader(session, m, buf); // will perform several buf.put()
calls
// Encode the body
encodeBody(session, m, buf); // will perform many buf.put() calls
buf.flip();
out.write(buf);
}
protected abstract void encodeMetadata(ProtocolSession session,
EasiAbstractMessage message, ByteBuffer buf);
protected abstract void encodeHeader(ProtocolSession session,
EasiAbstractMessage message, ByteBuffer buf);
protected abstract void encodeBody(ProtocolSession session,
EasiAbstractMessage message, ByteBuffer buf);
}
As you can see the buffer is acquired every time it is retrieved from the
session context object. Apparently Mina is releasing the buffer in the
out.write(buf) call, is that true?
What is Mina going to do with this buffer with regard to pooling?
Is Mina going to add it to its ByteBuffer pool?
Is what I am doing reasonable?
Is there a way that I can pass a ByteBuffer to Mina without having Mina take
ownership of that ByteBuffer?
At a high level, what this server needs to do is to be able to send 40 - 50
1K deal ticket per second down to a single client (with the nagle algorithm
disabled). BTW the client is very fast and almost always responds to the
deal ticket message within the same millisecond in which it was received.
Is it reasonable to expect this kind of performance from Mina?
Also worth noting is that the decoding, handling, retrieval of deal ticket
from the database, encoding and all of the related parsing etc. is very fast
and usually only takes around 10 to 20 milliseconds to complete.
Any help would be greatly appreciated! (Sorry for being so long winded!)
Thanks for all who work on Mina, a very elegant design which renders NIO
much more approachable.
Colin Cullen
_____
The information contained in this e-mail is for the exclusive use of the
intended recipient(s) and may be confidential, proprietary, and/or legally
privileged. Inadvertent disclosure of this message does not constitute a
waiver of any privilege. If you receive this message in error, please do
not directly or indirectly use, print, copy, forward, or disclose any part
of this message. Please also delete this e-mail and all copies and notify
the sender. Thank you.
_____
| |
| Trustin Lee 2006-04-20, 6:55 pm |
| Hi Colin,
On 4/18/06, Colin Cullen <colincullen-ihVZJaRskl1bRRN4PJnoQQ@public.gmane.org> wrote:
>
> Hi,
>
> I am seeking some help regarding Mina. I have completed development of a
> server using Mina 0.8.2. This server will be providing financial deal
> ticket information to multiple clients. Functionally everything works great
> but I do seem to have a memory leak and slowly degrading performance. I am
> testing using a single production level client (not Mina based). The server
> protocol sends a deal ticket down to the client and then awaits a high level
> acknowledgement from the client indicating whether the ticket has passed or
> failed client side validation. The performance degradation occurs between
> the writing of the message object (deal ticket) at the protocol level and
> the reception of the response message in its message handler. BTW I am
> using Mina's DemuxingProtocolCodecFactory and DemuxingProtocolHandler to
> model the server and provide the codec/handler glue. I am concerned about
> whether I am using Mina's ByteBuffer properly. I have also read on the
> board that Mina will automatically place an allocated ByteBuffer in its
> ByteBuffer pool.
>
MINA 0.8 doesn't release pooled buffers once allocated, so the pool size
will never decrease. This problem has been addressed in 0.9.3 which has
been released recently. Except that, there's no known memory leak in 0.8.
To prevent MINA from pooling the allocated buffers, just acquire them once
more, for example:
ByteBuffer buf = ByteBuffer.allocate(....);
buf.acquire(); // acquire once more.
> My output buffer requirements are pretty minimal. The deal ticket message
> is around 1K bytes. I allocate a single ByteBuffer for each session and
> keep it in the session object, which is stored in Mina's session context
> map, when a deal ticket needs to be written to the client the pre-allocated
> ByteBuffer is retrieved from the session context object and used for
> building the outbound data set. Here are the actual code fragments:
>
> This factory creates a session context object for each connection:
>
> public class SessionContextFactory
>
> {
>
> static private SessionContextFactory instance = new
> SessionContextFactory();
>
> static public SessionContextFactory getInstance()
>
> {
>
> return SessionContextFactory.instance;
>
> }
>
> private SessionContextFactory()
>
> {
>
> }
>
> public SessionContext createSessionContext(ProtocolSession session)
>
> {
>
> return new SessionContext(session);
>
> }
>
> public final class SessionContext implements SessionContext,
> LifeSpanControllable
>
> {
>
> ByteBuffer dataBuffer;
>
>
>
> private SessionContext(ProtocolSession session)
>
> {
>
> dataBuffer = ByteBuffer.allocate(1024);
>
> }
>
> public ByteBuffer getDataBuffer()
>
> {
>
> dataBuffer.acquire();'
>
> return dataBuffer;
>
> }
>
> }
>
> }
>
>
>
> This class performs the message encoding using the single ByteBuffer
> retrieved from the session context object:
>
>
>
> public abstract class EasiAbstractMessageEncoder implements MessageEncoder
>
> {
>
> private final String type;
>
>
>
> protected EasiAbstractMessageEncoder(String type)
>
> {
>
> this.type = type;
>
> }
>
> protected String getType()
>
> {
>
> return type;
>
> }
>
> public void encode(ProtocolSession session, Object message,
> ProtocolEncoderOutput out) throws ProtocolViolationException
>
> {
>
> SessionContext sessCtx = (SessionContext)session.getAttribute(
> ServerConstants.SESSION_CONTEXT);
>
> EasiAbstractMessage m = (EasiAbstractMessage)message;
>
>
>
> ByteBuffer buf = sessCtx.getDataBuffer();
>
> buf.clear();
>
> // Encode the header
>
> encodeHeader(session, m, buf); // will perform several buf.put()
> calls
>
> // Encode the body
>
> encodeBody(session, m, buf); // will perform many buf.put() calls
>
> buf.flip();
>
> out.write(buf);
>
> }
>
> protected abstract void encodeMetadata(ProtocolSession session,
> EasiAbstractMessage message, ByteBuffer buf);
>
> protected abstract void encodeHeader(ProtocolSession session,
> EasiAbstractMessage message, ByteBuffer buf);
>
> protected abstract void encodeBody(ProtocolSession session,
> EasiAbstractMessage message, ByteBuffer buf);
>
> }
>
>
>
> As you can see the buffer is acquired every time it is retrieved from the
> session context object. Apparently Mina is releasing the buffer in the
> out.write(buf) call, is that true?
>
Yes, it's true. This also means your dataBuffer will never return to the
MINA buffer pool because you acquired the buffer once more.
At a high level, what this server needs to do is to be able to send 40 – 50
> 1K deal ticket per second down to a single client (with the nagle algorithm
> disabled). BTW the client is very fast and almost always responds to the
> deal ticket message within the same millisecond in which it was received.
>
> Is it reasonable to expect this kind of performance from Mina?
>
Actually myself didn't push MINA that much. Anyone in the list might give
you some information.
> Also worth noting is that the decoding, handling, retrieval of deal ticket
> from the database, encoding and all of the related parsing etc. is very fast
> and usually only takes around 10 to 20 milliseconds to complete.
>
Your code looks OK to me. It would be nice if you can give us heap profiler
data so we can find out which objects are dominant.
> Any help would be greatly appreciated! (Sorry for being so long winded!)
>
No problem. Thank you for detailed information! 
> Thanks for all who work on Mina, a very elegant design which renders NIO
> much more approachable.
>
Your feedback will make MINA more robust and beautiful. Please don't
hesitate! ;)
HTH,
Trustin
--
what we call human nature is actually human habit
--
http://gleamynode.net/
--
PGP key fingerprints:
* E167 E6AF E73A CBCE EE41 4A29 544D DE48 FE95 4E7E
* B693 628E 6047 4F8F CFA4 455E 1C62 A7DC 0255 ECA6
| |
| Colin Cullen 2006-04-20, 6:56 pm |
| <HEAD>
<META content=3D"MSHTML 6.00.2800.1522" name=3DGENERATOR></HEAD>
<BODY>
<DIV>Hi Trustin,</DIV>
<DIV> </DIV>
<DIV>(Note: the following discussion is related to Mina 0.8.2.)</DIV>
<DIV> </DIV>
<DIV>Thanks for the quick response! I am using JProbe to profile the =
Mina based server. JProbe indicates a consistent memory leak which se=
ems to coincide with whenever a deal ticket message is sent. It also =
indicates a memory leak if I just let the heartbeat message run (using Mina=
's idle feature for this). The heartbeat message is under 100 bytes, =
to which the client app responds with a message of about 50 bytes, it runs =
when there is no other msg exchange activity. If I let heartbeat scen=
ario JProbe will again report a consistent leak. GC occurs but never =
seems to recover completely and memory consumption continues to rise throug=
hout the run.</DIV>
<DIV> </DIV>
<DIV>As I stated earlier the server is also having performance problems.&nb=
sp; It starts out fine, able to send a deal ticket and receive a deal ticke=
t ack with a latency of about 30 ms, but this time deterioriates at time go=
on. For example, I ran a test for about 6 hours last night where lat=
ency started out at about 30 ms, but by the end of the run latency was abou=
t 3000 ms. It is interesting to note that although the average latenc=
y increases with time, when I inspect the individual round trips toward the=
later parts of the test run, I see that the latency times vary greatly, an=
ywhere between 30 ms and 3000 ms, but with the majority of the latency time=
s being toward the high end.</DIV>
<DIV> </DIV>
<DIV>I am thinking that the leak and performance problems are related since=
they seem to occur under the same run conditions, although I am still digg=
ing for clues.</DIV>
<DIV> </DIV>
<DIV>I have searched the Mina board and I noticed others discussing ByteBuf=
fers with respect to leakage. I believe I read that these problems we=
re fixed and have adjusted my code accordingly, as per my coding example be=
low. I have also discovered that SUN had leakage problems regarding N=
IO and ByteBuffers in 1.4.x. I am using Java 1.5 -- I am still resear=
ching in this area as I just uncovered this fact last night.</DIV>
<DIV>I performed some timings on Mina's demuxing decoder model, thinking th=
at either the model and/or my NIO buffer parsing code was slow, but on the =
contrary is runs very fast and usually completes the decoding into a messag=
e all within the same millisecond.</DIV>
<DIV> </DIV>
<DIV>The problem has been isolated to the point where the out.write is call=
ed to send out the deal ticket message, and when the decoder is called for =
the inbound deal ticket ack message. I am running with 5 filters but =
have tried disabling 3 of them (the other 2 are essential) without any chan=
ge in performance or performance degredation. I did note, during the =
course of the development / debug cycle, that the call stack for Mina's fil=
ter mechanism can get really deep, but I assumed that this is normal behavi=
or, is that correct?</DIV>
<DIV> </DIV>
<DIV>I have debugged through some of Mina's code trying to understand the f=
low and possible find where things are getting slow. It looks like th=
e session's out.write is decoupled from the actual socket write by a queue =
(or queues) which naturally require synchronization. Any pointers for=
me here as to where to look regarding my problem?</DIV>
<DIV> </DIV>
<DIV>I can understand if performance is just not where I need it to be, but=
what I can't understand is that the performance starts out good but degrad=
es as time goes on, this indicates a bottleneck somewhere. I also won=
der why latency differs so widely in my test run. Is the outbound dat=
a sent in a bursty fashion?</DIV>
<DIV>Do you know if the SUN NIO ByteBuffer leakage problems have been addre=
ssed in Java 1.5? In Mina 0.8.2?</DIV>
<DIV> </DIV>
<DIV>Can you point me to the points where I should look to instrument Mina =
when the ticket message is written and where the ticket ack message is reci=
eved?</DIV>
<DIV> </DIV>
<DIV>I always suspect my own code first but things don't appear to be point=
ing in that direction, unless there is some error in my usage of ByteBuffer=
objects.</DIV>
<DIV> </DIV>
<DIV>I am thinking of using a aspect to checkout the timings on the methods=
between the out.write and upto the decoding of the message on the inbound =
side.</DIV>
<DIV> </DIV>
<DIV>I'm not an expert in JProbe, but would a snapshot be of use?</DIV>
<DIV> </DIV>
<DIV>I appreciate your help and appreciate any help you or the board member=
s can give me in this area.</DIV>
<DIV> </DIV>
<DIV>Thanks.<BR>Colin<BR><BR>-----Original Message----- <BR>From: Trustin L=
ee <TRUSTIN-8a+P9i1ojmF8zQARNC3f2A@public.gmane.org><BR>Sent: Apr 18, 2006 1:03 AM <BR>To: Apache Directo=
ry Developers List <DEV-cGqlvAj/CmS6sE8sARM4HtGeqqvjHH9B@public.gmane.org>, colincullen-ihVZJaRskl1bRRN4PJnoQQ@public.gmane.org <B=
R>Subject: Re: ByteBuffer usage, performance, leak <BR><BR>Hi Colin,<BR><BR=
></DIV>
<DIV><SPAN class=3Dgmail_quote>On 4/18/06, <B class=3Dgmail_sendername>Coli=
n Cullen</B> <<A href=3D"mailto:colincullen-ihVZJaRskl1bRRN4PJnoQQ@public.gmane.org">colincullen@e=
arthlink.net</A>> wrote:</SPAN>
<BLOCKQUOTE class=3Dgmail_quote style=3D"PADDING-LEFT: 1ex; MARGIN: 0pt 0pt=
0pt 0.8ex; BORDER-LEFT: rgb(204,204,204) 1px solid">
<DIV style=3D"DIRECTION: ltr">
<DIV>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial">Hi,</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial">I am seeking some help regarding Mina. I have completed devel=
opment of a server using Mina 0.8.2. This server will be providing fi=
nancial deal ticket information to multiple clients. Functionally eve=
rything works great but I do seem to have a memory leak and slowly degradin=
g performance. I am testing using a single production level client (n=
ot Mina based). The server protocol sends a deal ticket down to the c=
lient and then awaits a high level acknowledgement from the client indicati=
ng whether the ticket has passed or failed client side validation. Th=
e performance degradation occurs between the writing of the message object =
(deal ticket) at the protocol level and the reception of the response messa=
ge in its message handler. BTW I am using Mina's DemuxingProtocolCode=
cFactory and DemuxingProtocolHandler to model the server and provide the co=
dec/handler glue. I am concerned about whether I am using Mina's Byte=
Buffer properly. I have also read on the board that Mina will automat=
ically place an allocated ByteBuffer in its ByteBuffer pool.</SPAN></FONT><=
/P></DIV></DIV></BLOCKQUOTE>
<DIV>MINA 0.8 doesn't release pooled buffers once allocated, so the pool si=
ze will never decrease. This problem has been addressed in 0.9.3 whic=
h has been released recently. Except that, there's no known memory le=
ak in 0.8. To prevent MINA from pooling the allocated buffers, just a=
cquire them once more, for example:<BR><BR>ByteBuffer buf =3D ByteBuffer.al=
locate(....);<BR>buf.acquire(); // acquire once more.<BR></DIV>
<BLOCKQUOTE class=3Dgmail_quote style=3D"PADDING-LEFT: 1ex; MARGIN: 0pt 0pt=
0pt 0.8ex; BORDER-LEFT: rgb(204,204,204) 1px solid">
<DIV style=3D"DIRECTION: ltr">
<DIV>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial">My output buffer requirements are pretty minimal. The deal ti=
cket message is around 1K bytes. I allocate a single ByteBuffer for e=
ach session and keep it in the session object, which is stored in Mina's se=
ssion context map, when a deal ticket needs to be written to the client the=
pre-allocated ByteBuffer is retrieved from the session context object and =
used for building the outbound data set. Here are the actual code fra=
gments:</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial">This factory creates a session context object for each connection:<=
/SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial">public class SessionContextFactory</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial">{</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> static private SessionContextFactory instance =
=3D new SessionContextFactory();</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> static public SessionContextFactory getInstance(=
)</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> {</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> return SessionContextFac=
tory.instance;</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> }</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> private SessionContextFactory()</SPAN></FONT></P=
>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> {</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> }</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> public SessionContext createSessionContext(Proto=
colSession session)</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> {</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> return new SessionContex=
t(session);</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> }</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> public final class SessionContext implements Ses=
sionContext, LifeSpanControllable</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> {</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> ByteBuffer dataBuffer;</=
SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"></SPAN></FONT> </P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> private SessionContext(P=
rotocolSession session)</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> {</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> =
dataBuffer =3D ByteBuffer.allocate(1024);</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> }</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> public ByteBuffer getDat=
aBuffer()</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> {</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> =
dataBuffer.acquire();'</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> =
return dataBuffer;</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> }</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> }</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial">}</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"></SPAN></FONT> </P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial">This class performs the message encoding using the single ByteBuffe=
r retrieved from the session context object: </SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"></SPAN></FONT> </P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial">public abstract class EasiAbstractMessageEncoder implements Message=
Encoder</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial">{</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> private final String type;</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"></SPAN></FONT> </P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> protected EasiAbstractMessageEncoder(String type=
)</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> {</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> this.type =3D type;</SPA=
N></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> }</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> protected String getType()</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> {</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> return type;</SPAN></FON=
T></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> }</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> public void encode(ProtocolSession session, Obje=
ct message, ProtocolEncoderOutput out) throws ProtocolViolationException</S=
PAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> {</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> SessionContext sessCtx =
=3D (SessionContext)session.getAttribute(ServerConstants.SESSION_CONTEXT);<=
/SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> EasiAbstractMessage m =
=3D (EasiAbstractMessage)message;</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"></SPAN></FONT> </P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> ByteBuffer buf =3D sessC=
tx.getDataBuffer();</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> buf.clear();</SPAN></FON=
T></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> // Encode the header</SP=
AN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> encodeHeader(session, m,=
buf); // will perform several buf.put() calls</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> // Encode the body</SPAN=
></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> encodeBody(session, m, b=
uf); // will perform many buf.put() calls</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> buf.flip();</SPAN></FONT=
></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> out.write(buf);</SPAN></=
FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> }</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> protected abstract void encodeMetadata(ProtocolS=
ession session, EasiAbstractMessage message, ByteBuffer buf);</SPAN></FONT>=
</P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> protected abstract void encodeHeader(ProtocolSes=
sion session, EasiAbstractMessage message, ByteBuffer buf);</SPAN></FONT></=
P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"> protected abstract void encodeBody(ProtocolSessi=
on session, EasiAbstractMessage message, ByteBuffer buf);</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial">}</SPAN></FONT></P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial"></SPAN></FONT> </P>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial">As you can see the buffer is acquired every time it is retrieved fr=
om the session context object. Apparently Mina is releasing the buffe=
r in the out.write(buf) call, is that true?</SPAN></FONT></P></DIV></DIV></=
BLOCKQUOTE>
<DIV>Yes, it's true. This also means your dataBuffer will never retur=
n to the MINA buffer pool because you acquired the buffer once more. <BR><B=
R></DIV>
<BLOCKQUOTE class=3Dgmail_quote style=3D"PADDING-LEFT: 1ex; MARGIN: 0pt 0pt=
0pt 0.8ex; BORDER-LEFT: rgb(204,204,204) 1px solid">
<DIV style=3D"DIRECTION: ltr">
<DIV><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMIL=
Y: Arial">At a high level, what this server needs to do is to be able to se=
nd 40 ? 50 1K deal ticket per second down to a single client (with the nagl=
e algorithm disabled). BTW the client is very fast and almost always =
responds to the deal ticket message within the same millisecond in which it=
was received.</SPAN></FONT>=20
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial">Is it reasonable to expect this kind of performance from Mina?</SPA=
N></FONT></P></DIV></DIV></BLOCKQUOTE>
<DIV>Actually myself didn't push MINA that much. Anyone in the list m=
ight give you some information.<BR></DIV>
<BLOCKQUOTE class=3Dgmail_quote style=3D"PADDING-LEFT: 1ex; MARGIN: 0pt 0pt=
0pt 0.8ex; BORDER-LEFT: rgb(204,204,204) 1px solid">
<DIV style=3D"DIRECTION: ltr">
<DIV>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial">Also worth noting is that the decoding, handling, retrieval of deal=
ticket from the database, encoding and all of the related parsing etc. is =
very fast and usually only takes around 10 to 20 milliseconds to complete.<=
/SPAN></FONT></P></DIV></DIV></BLOCKQUOTE>
<DIV>Your code looks OK to me. It would be nice if you can give us heap pro=
filer data so we can find out which objects are dominant. <BR></DIV>
<BLOCKQUOTE class=3Dgmail_quote style=3D"PADDING-LEFT: 1ex; MARGIN: 0pt 0pt=
0pt 0.8ex; BORDER-LEFT: rgb(204,204,204) 1px solid">
<DIV style=3D"DIRECTION: ltr">
<DIV>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial">Any help would be greatly appreciated! (Sorry for being so lo=
ng winded!)</SPAN></FONT></P></DIV></DIV></BLOCKQUOTE>
<DIV>No problem. Thank you for detailed information! <BR></DIV>
<BLOCKQUOTE class=3Dgmail_quote style=3D"PADDING-LEFT: 1ex; MARGIN: 0pt 0pt=
0pt 0.8ex; BORDER-LEFT: rgb(204,204,204) 1px solid">
<DIV style=3D"DIRECTION: ltr">
<DIV>
<P><FONT face=3DArial size=3D2><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY:=
Arial">Thanks for all who work on Mina, a very elegant design which render=
s NIO much more approachable.</SPAN></FONT></P></DIV></DIV></BLOCKQUOTE>
<DIV>Your feedback will make MINA more robust and beautiful. Please d=
on't hesitate! ;)<BR> </DIV></DIV>
<DIV>HTH,<BR>Trustin<BR>-- <BR>what we call human nature is actually human =
habit <BR>--<BR><A href=3D"http://gleamynode.net/">http://gleamynode.net/</=
A><BR>--<BR>PGP key fingerprints:<BR>* E167 E6AF E73A CBCE EE41 =
4A29 544D DE48 FE95 4E7E<BR>* B693 628E 6047 4F8F CFA4 455E 1C62=
A7DC 0255 ECA6 </DIV></BODY>
| |
| Noel J. Bergman 2006-04-20, 6:56 pm |
| > (Note: the following discussion is related to Mina 0.8.2.)
MINA has its own mailing list: mina-dev-aYN4UCa7k1r1N9kud6OZblN6ohzGQtmt@public.gmane.org
--- Noel
|
|
|
|
|