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 fbc0ce4784
commit 3ebe2ee369
4 changed files with 531 additions and 522 deletions

View File

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

View File

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

View File

@ -148,12 +148,11 @@ public class Lz4FrameDecoder extends ByteToMessageDecoder {
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
for (;;) {
try {
switch (currentState) {
case INIT_BLOCK:
if (in.readableBytes() < HEADER_LENGTH) {
return;
break;
}
final long magic = in.readLong();
if (magic != MAGIC_NUMBER) {
@ -210,7 +209,7 @@ public class Lz4FrameDecoder extends ByteToMessageDecoder {
currentChecksum = this.currentChecksum;
if (in.readableBytes() < compressedLength) {
return;
break;
}
final int idx = in.readerIndex();
@ -283,7 +282,7 @@ public class Lz4FrameDecoder extends ByteToMessageDecoder {
case FINISHED:
case CORRUPTED:
in.skipBytes(in.readableBytes());
return;
break;
default:
throw new IllegalStateException();
}
@ -292,7 +291,6 @@ public class Lz4FrameDecoder extends ByteToMessageDecoder {
throw e;
}
}
}
/**
* 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
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
for (;;) {
try {
switch (currentState) {
case INIT_BLOCK:
if (in.readableBytes() < HEADER_LEN_NOT_COMPRESSED) {
return;
break;
}
final int magic = in.readUnsignedShort();
if (magic != MAGIC_NUMBER) {
@ -143,7 +142,7 @@ public class LzfDecoder extends ByteToMessageDecoder {
}
case INIT_ORIGINAL_LENGTH:
if (in.readableBytes() < 2) {
return;
break;
}
originalLength = in.readUnsignedShort();
@ -151,7 +150,7 @@ public class LzfDecoder extends ByteToMessageDecoder {
case DECOMPRESS_DATA:
final int chunkLength = this.chunkLength;
if (in.readableBytes() < chunkLength) {
return;
break;
}
final int originalLength = this.originalLength;
@ -189,7 +188,7 @@ public class LzfDecoder extends ByteToMessageDecoder {
if (!in.hasArray()) {
recycler.releaseInputBuffer(inputArray);
}
} else {
} else if (chunkLength > 0) {
out.add(in.readSlice(chunkLength).retain());
}
@ -197,7 +196,7 @@ public class LzfDecoder extends ByteToMessageDecoder {
break;
case CORRUPTED:
in.skipBytes(in.readableBytes());
return;
break;
default:
throw new IllegalStateException();
}
@ -209,4 +208,3 @@ public class LzfDecoder extends ByteToMessageDecoder {
}
}
}
}