FastLzFrameDecoder should not need to do any extra memory copies even when direct buffers are used (#11511)
Modifications: Change code to not depend on heap buffers Result: Less memory copies
This commit is contained in:
parent
5eb9445990
commit
60c9cbf46a
@ -15,6 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.handler.codec.compression;
|
package io.netty.handler.codec.compression;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Core of FastLZ compression algorithm.
|
* Core of FastLZ compression algorithm.
|
||||||
*
|
*
|
||||||
@ -422,10 +424,10 @@ final class FastLz {
|
|||||||
* Decompression is memory safe and guaranteed not to write the output buffer
|
* Decompression is memory safe and guaranteed not to write the output buffer
|
||||||
* more than what is specified in outLength.
|
* more than what is specified in outLength.
|
||||||
*/
|
*/
|
||||||
static int decompress(final byte[] input, final int inOffset, final int inLength,
|
static int decompress(final ByteBuf input, final int inOffset, final int inLength,
|
||||||
final byte[] output, final int outOffset, final int outLength) {
|
final ByteBuf output, final int outOffset, final int outLength) {
|
||||||
//int level = ((*(const flzuint8*)input) >> 5) + 1;
|
//int level = ((*(const flzuint8*)input) >> 5) + 1;
|
||||||
final int level = (input[inOffset] >> 5) + 1;
|
final int level = (input.getByte(inOffset) >> 5) + 1;
|
||||||
if (level != LEVEL_1 && level != LEVEL_2) {
|
if (level != LEVEL_1 && level != LEVEL_2) {
|
||||||
throw new DecompressionException(String.format(
|
throw new DecompressionException(String.format(
|
||||||
"invalid level: %d (expected: %d or %d)", level, LEVEL_1, LEVEL_2
|
"invalid level: %d (expected: %d or %d)", level, LEVEL_1, LEVEL_2
|
||||||
@ -437,7 +439,7 @@ final class FastLz {
|
|||||||
// flzuint8* op = (flzuint8*) output;
|
// flzuint8* op = (flzuint8*) output;
|
||||||
int op = 0;
|
int op = 0;
|
||||||
// flzuint32 ctrl = (*ip++) & 31;
|
// flzuint32 ctrl = (*ip++) & 31;
|
||||||
long ctrl = input[inOffset + ip++] & 31;
|
long ctrl = input.getByte(inOffset + ip++) & 31;
|
||||||
|
|
||||||
int loop = 1;
|
int loop = 1;
|
||||||
do {
|
do {
|
||||||
@ -457,27 +459,27 @@ final class FastLz {
|
|||||||
if (len == 6) {
|
if (len == 6) {
|
||||||
if (level == LEVEL_1) {
|
if (level == LEVEL_1) {
|
||||||
// len += *ip++;
|
// len += *ip++;
|
||||||
len += input[inOffset + ip++] & 0xFF;
|
len += input.getUnsignedByte(inOffset + ip++);
|
||||||
} else {
|
} else {
|
||||||
do {
|
do {
|
||||||
code = input[inOffset + ip++] & 0xFF;
|
code = input.getUnsignedByte(inOffset + ip++);
|
||||||
len += code;
|
len += code;
|
||||||
} while (code == 255);
|
} while (code == 255);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (level == LEVEL_1) {
|
if (level == LEVEL_1) {
|
||||||
// ref -= *ip++;
|
// ref -= *ip++;
|
||||||
ref -= input[inOffset + ip++] & 0xFF;
|
ref -= input.getUnsignedByte(inOffset + ip++);
|
||||||
} else {
|
} else {
|
||||||
code = input[inOffset + ip++] & 0xFF;
|
code = input.getUnsignedByte(inOffset + ip++);
|
||||||
ref -= code;
|
ref -= code;
|
||||||
|
|
||||||
/* match from 16-bit distance */
|
/* match from 16-bit distance */
|
||||||
// if(FASTLZ_UNEXPECT_CONDITIONAL(code==255))
|
// if(FASTLZ_UNEXPECT_CONDITIONAL(code==255))
|
||||||
// if(FASTLZ_EXPECT_CONDITIONAL(ofs==(31 << 8)))
|
// if(FASTLZ_EXPECT_CONDITIONAL(ofs==(31 << 8)))
|
||||||
if (code == 255 && ofs == 31 << 8) {
|
if (code == 255 && ofs == 31 << 8) {
|
||||||
ofs = (input[inOffset + ip++] & 0xFF) << 8;
|
ofs = input.getUnsignedByte(inOffset + ip++) << 8;
|
||||||
ofs += input[inOffset + ip++] & 0xFF;
|
ofs += input.getUnsignedByte(inOffset + ip++);
|
||||||
|
|
||||||
ref = (int) (op - ofs - MAX_DISTANCE);
|
ref = (int) (op - ofs - MAX_DISTANCE);
|
||||||
}
|
}
|
||||||
@ -496,7 +498,7 @@ final class FastLz {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ip < inLength) {
|
if (ip < inLength) {
|
||||||
ctrl = input[inOffset + ip++] & 0xFF;
|
ctrl = input.getUnsignedByte(inOffset + ip++);
|
||||||
} else {
|
} else {
|
||||||
loop = 0;
|
loop = 0;
|
||||||
}
|
}
|
||||||
@ -504,12 +506,12 @@ final class FastLz {
|
|||||||
if (ref == op) {
|
if (ref == op) {
|
||||||
/* optimize copy for a run */
|
/* optimize copy for a run */
|
||||||
// flzuint8 b = ref[-1];
|
// flzuint8 b = ref[-1];
|
||||||
byte b = output[outOffset + ref - 1];
|
byte b = output.getByte(outOffset + ref - 1);
|
||||||
output[outOffset + op++] = b;
|
output.setByte(outOffset + op++, b);
|
||||||
output[outOffset + op++] = b;
|
output.setByte(outOffset + op++, b);
|
||||||
output[outOffset + op++] = b;
|
output.setByte(outOffset + op++, b);
|
||||||
while (len != 0) {
|
while (len != 0) {
|
||||||
output[outOffset + op++] = b;
|
output.setByte(outOffset + op++, b);
|
||||||
--len;
|
--len;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -517,12 +519,12 @@ final class FastLz {
|
|||||||
ref--;
|
ref--;
|
||||||
|
|
||||||
// *op++ = *ref++;
|
// *op++ = *ref++;
|
||||||
output[outOffset + op++] = output[outOffset + ref++];
|
output.setByte(outOffset + op++, output.getByte(outOffset + ref++));
|
||||||
output[outOffset + op++] = output[outOffset + ref++];
|
output.setByte(outOffset + op++, output.getByte(outOffset + ref++));
|
||||||
output[outOffset + op++] = output[outOffset + ref++];
|
output.setByte(outOffset + op++, output.getByte(outOffset + ref++));
|
||||||
|
|
||||||
while (len != 0) {
|
while (len != 0) {
|
||||||
output[outOffset + op++] = output[outOffset + ref++];
|
output.setByte(outOffset + op++, output.getByte(outOffset + ref++));
|
||||||
--len;
|
--len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -537,17 +539,17 @@ final class FastLz {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//*op++ = *ip++;
|
//*op++ = *ip++;
|
||||||
output[outOffset + op++] = input[inOffset + ip++];
|
output.setByte(outOffset + op++, input.getByte(inOffset + ip++));
|
||||||
|
|
||||||
for (--ctrl; ctrl != 0; ctrl--) {
|
for (--ctrl; ctrl != 0; ctrl--) {
|
||||||
// *op++ = *ip++;
|
// *op++ = *ip++;
|
||||||
output[outOffset + op++] = input[inOffset + ip++];
|
output.setByte(outOffset + op++, input.getByte(inOffset + ip++));
|
||||||
}
|
}
|
||||||
|
|
||||||
loop = ip < inLength ? 1 : 0;
|
loop = ip < inLength ? 1 : 0;
|
||||||
if (loop != 0) {
|
if (loop != 0) {
|
||||||
// ctrl = *ip++;
|
// ctrl = *ip++;
|
||||||
ctrl = input[inOffset + ip++] & 0xFF;
|
ctrl = input.getUnsignedByte(inOffset + ip++);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,21 +148,11 @@ public class FastLzFrameDecoder extends ByteToMessageDecoder {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (isCompressed) {
|
if (isCompressed) {
|
||||||
final byte[] input;
|
|
||||||
final int inputOffset;
|
|
||||||
if (in.hasArray()) {
|
|
||||||
input = in.array();
|
|
||||||
inputOffset = in.arrayOffset() + idx;
|
|
||||||
} else {
|
|
||||||
input = new byte[chunkLength];
|
|
||||||
in.getBytes(idx, input);
|
|
||||||
inputOffset = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
output = ctx.alloc().heapBuffer(originalLength);
|
output = ctx.alloc().buffer(originalLength);
|
||||||
int outputOffset = output.arrayOffset() + output.writerIndex();
|
int outputOffset = output.writerIndex();
|
||||||
final int decompressedBytes = decompress(input, inputOffset, chunkLength,
|
final int decompressedBytes = decompress(in, idx, chunkLength,
|
||||||
output.array(), outputOffset, originalLength);
|
output, outputOffset, originalLength);
|
||||||
if (originalLength != decompressedBytes) {
|
if (originalLength != decompressedBytes) {
|
||||||
throw new DecompressionException(String.format(
|
throw new DecompressionException(String.format(
|
||||||
"stream corrupted: originalLength(%d) and actual length(%d) mismatch",
|
"stream corrupted: originalLength(%d) and actual length(%d) mismatch",
|
||||||
|
Loading…
Reference in New Issue
Block a user