Use offset finding eol avoid repeated scaning.
Motivation: A large frame will be componsed by many packages. Every time the package arrived, findEndOfLine will be called from the start of the buffer. It will cause the complexity of reading frame equal to O(n^2). This can be eliminated by using a offset to mark the last scan position, when new package arrived, just find the delimter from the mark. The complexity will be O(n). Modification: Add a offset to mark the last scan position. Result: Better performance for read large frame.
This commit is contained in:
parent
282aa35682
commit
80b8a91b70
@ -39,6 +39,9 @@ public class LineBasedFrameDecoder extends ByteToMessageDecoder {
|
||||
private boolean discarding;
|
||||
private int discardedBytes;
|
||||
|
||||
/** Last scan position. */
|
||||
private int offset;
|
||||
|
||||
/**
|
||||
* Creates a new decoder.
|
||||
* @param maxLength the maximum length of the decoded frame.
|
||||
@ -114,6 +117,7 @@ public class LineBasedFrameDecoder extends ByteToMessageDecoder {
|
||||
discardedBytes = length;
|
||||
buffer.readerIndex(buffer.writerIndex());
|
||||
discarding = true;
|
||||
offset = 0;
|
||||
if (failFast) {
|
||||
fail(ctx, "over " + discardedBytes);
|
||||
}
|
||||
@ -152,10 +156,16 @@ public class LineBasedFrameDecoder extends ByteToMessageDecoder {
|
||||
* Returns the index in the buffer of the end of line found.
|
||||
* Returns -1 if no end of line was found in the buffer.
|
||||
*/
|
||||
private static int findEndOfLine(final ByteBuf buffer) {
|
||||
int i = buffer.forEachByte(ByteProcessor.FIND_LF);
|
||||
if (i > 0 && buffer.getByte(i - 1) == '\r') {
|
||||
i--;
|
||||
private int findEndOfLine(final ByteBuf buffer) {
|
||||
int totalLength = buffer.readableBytes();
|
||||
int i = buffer.forEachByte(buffer.readerIndex() + offset, totalLength - offset, ByteProcessor.FIND_LF);
|
||||
if (i >= 0) {
|
||||
offset = 0;
|
||||
if (i > 0 && buffer.getByte(i - 1) == '\r') {
|
||||
i--;
|
||||
}
|
||||
} else {
|
||||
offset = totalLength;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
@ -167,4 +167,22 @@ public class LineBasedFrameDecoderTest {
|
||||
buf.release();
|
||||
buf2.release();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyLine() throws Exception {
|
||||
EmbeddedChannel ch = new EmbeddedChannel(new LineBasedFrameDecoder(8192, true, false));
|
||||
|
||||
assertTrue(ch.writeInbound(copiedBuffer("\nabcna\r\n", CharsetUtil.US_ASCII)));
|
||||
|
||||
ByteBuf buf = ch.readInbound();
|
||||
assertEquals("", buf.toString(CharsetUtil.US_ASCII));
|
||||
|
||||
ByteBuf buf2 = ch.readInbound();
|
||||
assertEquals("abcna", buf2.toString(CharsetUtil.US_ASCII));
|
||||
|
||||
assertFalse(ch.finishAndReleaseAll());
|
||||
|
||||
buf.release();
|
||||
buf2.release();
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user