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.