Remove unnecessary loop and indentation in decompressors

Motivation:

Decompression handlers contain heavy use of switch-case statements. We
use compact indentation style for 'case' so that we utilize our screen
real-estate more efficiently.

Also, the following decompression handlers do not need to run a loop,
because ByteToMessageDecoder already runs a loop for them:

- FastLzFrameDecoder
- Lz4FrameDecoder
- LzfDecoder

Modifications:

- Fix indentations
- Do not wrap the decoding logic with a for loop when unnecessary
- Handle the case where a FastLz/Lzf frame contains no data properly so
  that the buffer does not leak and less garbage is produced.

Result:

- Efficiency
- Compact source code
- No buffer leak
This commit is contained in:
Trustin Lee 2015-01-12 00:13:15 +09:00
parent 79450e081b
commit ad4418cf9b
4 changed files with 531 additions and 522 deletions

View File

@ -81,6 +81,7 @@ public class Bzip2Decoder extends ByteToMessageDecoder {
if (!in.isReadable()) { if (!in.isReadable()) {
return; return;
} }
final Bzip2BitReader reader = this.reader; final Bzip2BitReader reader = this.reader;
reader.setByteBuf(in); reader.setByteBuf(in);

View File

@ -18,6 +18,7 @@ package io.netty.handler.codec.compression;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder; import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.util.internal.EmptyArrays;
import java.util.List; import java.util.List;
import java.util.zip.Adler32; import java.util.zip.Adler32;
@ -108,12 +109,11 @@ public class FastLzFrameDecoder extends ByteToMessageDecoder {
@Override @Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
for (;;) {
try { try {
switch (currentState) { switch (currentState) {
case INIT_BLOCK: case INIT_BLOCK:
if (in.readableBytes() < 4) { if (in.readableBytes() < 4) {
return; break;
} }
final int magic = in.readUnsignedMedium(); final int magic = in.readUnsignedMedium();
@ -128,7 +128,7 @@ public class FastLzFrameDecoder extends ByteToMessageDecoder {
currentState = State.INIT_BLOCK_PARAMS; currentState = State.INIT_BLOCK_PARAMS;
case INIT_BLOCK_PARAMS: case INIT_BLOCK_PARAMS:
if (in.readableBytes() < 2 + (isCompressed ? 2 : 0) + (hasChecksum ? 4 : 0)) { if (in.readableBytes() < 2 + (isCompressed ? 2 : 0) + (hasChecksum ? 4 : 0)) {
return; break;
} }
currentChecksum = hasChecksum ? in.readInt() : 0; currentChecksum = hasChecksum ? in.readInt() : 0;
chunkLength = in.readUnsignedShort(); chunkLength = in.readUnsignedShort();
@ -138,15 +138,25 @@ public class FastLzFrameDecoder extends ByteToMessageDecoder {
case DECOMPRESS_DATA: case DECOMPRESS_DATA:
final int chunkLength = this.chunkLength; final int chunkLength = this.chunkLength;
if (in.readableBytes() < chunkLength) { if (in.readableBytes() < chunkLength) {
return; break;
} }
final int idx = in.readerIndex(); final int idx = in.readerIndex();
final int originalLength = this.originalLength; final int originalLength = this.originalLength;
ByteBuf uncompressed = ctx.alloc().heapBuffer(originalLength, originalLength); final ByteBuf uncompressed;
final byte[] output = uncompressed.array(); final byte[] output;
final int outputPtr = uncompressed.arrayOffset() + uncompressed.writerIndex(); final int outputPtr;
if (originalLength != 0) {
uncompressed = ctx.alloc().heapBuffer(originalLength, originalLength);
output = uncompressed.array();
outputPtr = uncompressed.arrayOffset() + uncompressed.writerIndex();
} else {
uncompressed = null;
output = EmptyArrays.EMPTY_BYTES;
outputPtr = 0;
}
boolean success = false; boolean success = false;
try { try {
@ -184,8 +194,11 @@ public class FastLzFrameDecoder extends ByteToMessageDecoder {
checksumResult, currentChecksum)); checksumResult, currentChecksum));
} }
} }
if (uncompressed != null) {
uncompressed.writerIndex(uncompressed.writerIndex() + originalLength); uncompressed.writerIndex(uncompressed.writerIndex() + originalLength);
out.add(uncompressed); out.add(uncompressed);
}
in.skipBytes(chunkLength); in.skipBytes(chunkLength);
currentState = State.INIT_BLOCK; currentState = State.INIT_BLOCK;
@ -198,7 +211,7 @@ public class FastLzFrameDecoder extends ByteToMessageDecoder {
break; break;
case CORRUPTED: case CORRUPTED:
in.skipBytes(in.readableBytes()); in.skipBytes(in.readableBytes());
return; break;
default: default:
throw new IllegalStateException(); throw new IllegalStateException();
} }
@ -208,4 +221,3 @@ public class FastLzFrameDecoder extends ByteToMessageDecoder {
} }
} }
} }
}

View File

@ -148,12 +148,11 @@ public class Lz4FrameDecoder extends ByteToMessageDecoder {
@Override @Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
for (;;) {
try { try {
switch (currentState) { switch (currentState) {
case INIT_BLOCK: case INIT_BLOCK:
if (in.readableBytes() < HEADER_LENGTH) { if (in.readableBytes() < HEADER_LENGTH) {
return; break;
} }
final long magic = in.readLong(); final long magic = in.readLong();
if (magic != MAGIC_NUMBER) { if (magic != MAGIC_NUMBER) {
@ -210,7 +209,7 @@ public class Lz4FrameDecoder extends ByteToMessageDecoder {
currentChecksum = this.currentChecksum; currentChecksum = this.currentChecksum;
if (in.readableBytes() < compressedLength) { if (in.readableBytes() < compressedLength) {
return; break;
} }
final int idx = in.readerIndex(); final int idx = in.readerIndex();
@ -283,7 +282,7 @@ public class Lz4FrameDecoder extends ByteToMessageDecoder {
case FINISHED: case FINISHED:
case CORRUPTED: case CORRUPTED:
in.skipBytes(in.readableBytes()); in.skipBytes(in.readableBytes());
return; break;
default: default:
throw new IllegalStateException(); throw new IllegalStateException();
} }
@ -292,7 +291,6 @@ public class Lz4FrameDecoder extends ByteToMessageDecoder {
throw e; throw e;
} }
} }
}
/** /**
* Returns {@code true} if and only if the end of the compressed stream * Returns {@code true} if and only if the end of the compressed stream

View File

@ -109,12 +109,11 @@ public class LzfDecoder extends ByteToMessageDecoder {
@Override @Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
for (;;) {
try { try {
switch (currentState) { switch (currentState) {
case INIT_BLOCK: case INIT_BLOCK:
if (in.readableBytes() < HEADER_LEN_NOT_COMPRESSED) { if (in.readableBytes() < HEADER_LEN_NOT_COMPRESSED) {
return; break;
} }
final int magic = in.readUnsignedShort(); final int magic = in.readUnsignedShort();
if (magic != MAGIC_NUMBER) { if (magic != MAGIC_NUMBER) {
@ -143,7 +142,7 @@ public class LzfDecoder extends ByteToMessageDecoder {
} }
case INIT_ORIGINAL_LENGTH: case INIT_ORIGINAL_LENGTH:
if (in.readableBytes() < 2) { if (in.readableBytes() < 2) {
return; break;
} }
originalLength = in.readUnsignedShort(); originalLength = in.readUnsignedShort();
@ -151,7 +150,7 @@ public class LzfDecoder extends ByteToMessageDecoder {
case DECOMPRESS_DATA: case DECOMPRESS_DATA:
final int chunkLength = this.chunkLength; final int chunkLength = this.chunkLength;
if (in.readableBytes() < chunkLength) { if (in.readableBytes() < chunkLength) {
return; break;
} }
final int originalLength = this.originalLength; final int originalLength = this.originalLength;
@ -189,7 +188,7 @@ public class LzfDecoder extends ByteToMessageDecoder {
if (!in.hasArray()) { if (!in.hasArray()) {
recycler.releaseInputBuffer(inputArray); recycler.releaseInputBuffer(inputArray);
} }
} else { } else if (chunkLength > 0) {
out.add(in.readSlice(chunkLength).retain()); out.add(in.readSlice(chunkLength).retain());
} }
@ -197,7 +196,7 @@ public class LzfDecoder extends ByteToMessageDecoder {
break; break;
case CORRUPTED: case CORRUPTED:
in.skipBytes(in.readableBytes()); in.skipBytes(in.readableBytes());
return; break;
default: default:
throw new IllegalStateException(); throw new IllegalStateException();
} }
@ -209,4 +208,3 @@ public class LzfDecoder extends ByteToMessageDecoder {
} }
} }
} }
}