Please see my comments in line.
Rob Butler wrote:
Hello all,
I've a few quick questions regarding byte buffers and recycling in
Mina.
Let's say I've got two connections to a Mina server. I'm sending
messages consisting of a "header" and "body" and I want to move
messages these between the two connections. The header on the
incoming message will be stripped off and replaced with a new header
before the message is sent to the other connection. With fixed size
headers I'd normally use scatter gather operations to efficiently
"parse" these messages into the two parts. Is this still possible
with Mina? How would I do this?
>
The key to building an efficient server is to minimize GC. To that
end, my initial though for passing messages between these two
connections is to simply take the byte buffer passed during
messageReceived and pass it to the other IoSession.write(..). But I
don't think this will work properly because of byte buffer recycling.
The incoming byte buffer could be "recycled" by mina before the
outgoing IoSession.write(..) happened. This would cause corruption
of the data. What is the best way to move bytes between two streams
without unnecessarily creating lots of short lived buffers or other
objects?
A number of Mina users have reported better performance using heap
buffers instead of direct buffers.
See the section "ByteBuffer Pooling Has Been Removed, and a Heap Buffer
is the Default Buffer Type" at
http://mina.apache.org/changes-between-2x-and-1x.html as well as this
entry from the FAQ
http://mina.apache.org/faq.html#FAQ-Iget%7B%7BOutOfMemoryError%7D%7Dorresponsetimeoutandconnectionresetunderheavyload.
One of the benefits of NIO is moving bytes between streams "in the
kernel". I.E. you don't have to bring the data into "user space" to
copy it from one stream to another and this reduces kernel context
switches. How do I take advantage of this in Mina?
Once data is put into a ByteBuffer, it is in user space. Direct buffers
having nothing to do with user space vs. kernel space. With Java NIO,
you can only take advantage of "zero copy" between streams if you use a
FileChannel and use transferTo (write the contents of the file to
another file or socket) or transferFrom (read data from another file or
socket and write it to the file.) If there is a zero copy socket to
socket available in Java, I am unaware of it. MINA 2 will include
support for utilizing FileChannel.transferTo for efficiently writing
file data to the remote host.
Basically I'm looking for the most efficient way to move bytes from
one stream to another. These bytes will actually be "messages" with
a header and body. The header will be changed between reception and
transmission. I also need to perform some routing logic using the
header. If necessary for efficiency I could use a fixed size header,
but would prefer not to.
If you turn off buffer pooling per the FAQ entry I mentioned above, you
can just write the ByteBuffer from messageReceived to IoSession.write
and it should work fine and still be very efficient.
-Mike