becareful with ReplayingDecoder; the way it is implemented it makes it costly
|
|

Thank's, I mostly use Netty.





I originally used mina, however, after reading through some articles, I realized that iobuffer was being scrapped (it was always handy and easy to use imo). I was faced with the dilemma that after mina3 came out I would be forced to redo most of my networking related code to keep updating my api. I did a very large amount of looking into it, and was kind of midway between netty and nio. However, the complexity and overhead of netty was a major turnoff for me. I ended up choosing nio and then implementing the reactor design pattern using both twisted and netty as guidance. After I finished, I have never looked back on my decision although it was possibly one of the most time consuming tasks that I have ever done.

I remember doing tests with it and using state management improved like 75% on a low amount of packets per minute and when packets per minute became higher the difference became less. It's a very usefull decoder if there is a lot of continuous traffic and the state management will lower the overhead in any situation and is very usefull to handle broken packets.
I can try and see if I still have it somewhere, I remember I send packets with a size of 16 bytes, varying from sending 1/minute upto like 15000/minute.
I used it for breaking up packets into frames and I really like it:
Code:@ChannelPipelineCoverage("one") public class GPPStreamMultiplexer extends ReplayingDecoder<DecoderState> { public GPPStreamMultiplexer() { super(DecoderState.READ_OPCODE); } @Override protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer, DecoderState state) throws Exception { ChannelBuffer b = ChannelBuffers.dynamicBuffer(256); int opcode = 0; int length = 0; switch (state) { case READ_OPCODE: opcode = buffer.readUnsignedByte(); b.writeByte((byte) opcode); checkpoint(DecoderState.READ_BODY); case READ_BODY: length = PacketHandlingExecutor.GPP_PACKET_LENGTHS[opcode]; switch (length) { case -3: length = actualReadableBytes(); Logger.log("Unframed packet with opcode " + opcode + " and estimated length: " + (length - 1)); buffer.skipBytes(length); break; case -2: length = buffer.readUnsignedShort(); b.writeShort((short) length); b.writeBytes(buffer, length); break; case -1: length = buffer.readUnsignedByte(); b.writeShort((short) length); b.writeBytes(buffer, length); break; case 0: b.writeShort((short) length); break; default: b.writeShort((short) length); b.writeBytes(buffer, length); break; } checkpoint(DecoderState.READ_OPCODE); return b; default: throw new Exception("GPPStreamMultiplexer failed"); } } }




The problem with it Maxi is that a slow client could cause it to decode parts of the message multiple times and each time it fails to decode something due to not enough data being present it'll throw an exception.
A FrameDecoder isn't really that much harder to understand - but it doesn't use any of the exception trickery behind your back and if you have a slow client you'll end up with better performance.
Now, you might think this is a bit of premature optimization. Perhaps it is. But if you are designing your server to support 2000 players, this is some code that is going to be called tens of thousands or maybe even hundreds of thousands time per second and you really want it to execute as quickly as possible so you don't get packets queueing up (which could ultimately lead to an OutOfMemoryError).
Netty, in my opinion, is less complicated and easier to understand than MINA. And also various benchmarks (that I've seen and perform myself) seem to indicate that in most situations Netty has less overhead than MINA.
The thing I do like about Netty is it tries to force you to decouple message decoding/encoding, message representation and message handling which from a design perspective is really good.

Nah, because what you said to Maxi is valid and should be a concern. You could probably help it by having more "states", but there's really no point if your code gets too complicated, and you'll lose the advantage of ReplayingDecoder anyway. Perhaps use ReplayingDecoder for debugging purposes and then FrameDecoder for the real deal.
| « Are there any server's that's worth playing? | Old school server. » |
| Thread Information |
Users Browsing this ThreadThere are currently 1 users browsing this thread. (0 members and 1 guests) |