Use ByteBufUtil.BYTE_ARRAYS ThreadLocal temporary arrays in more places (#8464)
Motivation: #8388 introduced a reusable ThreadLocal<byte[]> for use in decodeString(...). It can be used in more places in the buffer package to avoid temporary allocations of small arrays. Modifications: Encapsulate use of the ThreadLocal in a static package-private ByteBufUtil.threadLocalTempArray(int) method, and make use of it from a handful of new places including ByteBufUtil.readBytes(...). Result: Fewer short-lived small byte array allocations.
This commit is contained in:
parent
10539f4dc7
commit
5954110b9a
@ -56,7 +56,7 @@ public final class ByteBufUtil {
|
||||
private static final FastThreadLocal<byte[]> BYTE_ARRAYS = new FastThreadLocal<byte[]>() {
|
||||
@Override
|
||||
protected byte[] initialValue() throws Exception {
|
||||
return PlatformDependent.allocateUninitializedArray(1024);
|
||||
return PlatformDependent.allocateUninitializedArray(MAX_TL_ARRAY_LEN);
|
||||
}
|
||||
};
|
||||
|
||||
@ -95,6 +95,16 @@ public final class ByteBufUtil {
|
||||
logger.debug("-Dio.netty.maxThreadLocalCharBufferSize: {}", MAX_CHAR_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
static final int MAX_TL_ARRAY_LEN = 1024;
|
||||
|
||||
/**
|
||||
* Allocates a new array if minLength > {@link ByteBufUtil#MAX_TL_ARRAY_LEN}
|
||||
*/
|
||||
static byte[] threadLocalTempArray(int minLength) {
|
||||
return minLength <= MAX_TL_ARRAY_LEN ? BYTE_ARRAYS.get()
|
||||
: PlatformDependent.allocateUninitializedArray(minLength);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a <a href="http://en.wikipedia.org/wiki/Hex_dump">hex dump</a>
|
||||
* of the specified buffer's readable bytes.
|
||||
@ -768,11 +778,7 @@ public final class ByteBufUtil {
|
||||
array = src.array();
|
||||
offset = src.arrayOffset() + readerIndex;
|
||||
} else {
|
||||
if (len <= 1024) {
|
||||
array = BYTE_ARRAYS.get();
|
||||
} else {
|
||||
array = PlatformDependent.allocateUninitializedArray(len);
|
||||
}
|
||||
array = threadLocalTempArray(len);
|
||||
offset = 0;
|
||||
src.getBytes(readerIndex, array, 0, len);
|
||||
}
|
||||
@ -1392,7 +1398,9 @@ public final class ByteBufUtil {
|
||||
int chunkLen = Math.min(length, WRITE_CHUNK_SIZE);
|
||||
buffer.clear().position(position);
|
||||
|
||||
if (allocator.isDirectBufferPooled()) {
|
||||
if (length <= MAX_TL_ARRAY_LEN || !allocator.isDirectBufferPooled()) {
|
||||
getBytes(buffer, threadLocalTempArray(length), 0, chunkLen, out, length);
|
||||
} else {
|
||||
// if direct buffers are pooled chances are good that heap buffers are pooled as well.
|
||||
ByteBuf tmpBuf = allocator.heapBuffer(chunkLen);
|
||||
try {
|
||||
@ -1402,9 +1410,6 @@ public final class ByteBufUtil {
|
||||
} finally {
|
||||
tmpBuf.release();
|
||||
}
|
||||
} else {
|
||||
byte[] tmp = PlatformDependent.allocateUninitializedArray(length);
|
||||
getBytes(buffer, tmp, 0, chunkLen, out, length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,6 @@
|
||||
package io.netty.buffer;
|
||||
|
||||
import io.netty.util.Recycler;
|
||||
import io.netty.util.internal.PlatformDependent;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@ -352,8 +351,8 @@ final class PooledDirectByteBuf extends PooledByteBuf<ByteBuffer> {
|
||||
@Override
|
||||
public int setBytes(int index, InputStream in, int length) throws IOException {
|
||||
checkIndex(index, length);
|
||||
byte[] tmp = PlatformDependent.allocateUninitializedArray(length);
|
||||
int readBytes = in.read(tmp);
|
||||
byte[] tmp = ByteBufUtil.threadLocalTempArray(length);
|
||||
int readBytes = in.read(tmp, 0, length);
|
||||
if (readBytes <= 0) {
|
||||
return readBytes;
|
||||
}
|
||||
|
@ -15,7 +15,6 @@
|
||||
*/
|
||||
package io.netty.buffer;
|
||||
|
||||
import io.netty.util.internal.PlatformDependent;
|
||||
import io.netty.util.internal.StringUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -356,11 +355,11 @@ class ReadOnlyByteBufferBuf extends AbstractReferenceCountedByteBuf {
|
||||
if (buffer.hasArray()) {
|
||||
out.write(buffer.array(), index + buffer.arrayOffset(), length);
|
||||
} else {
|
||||
byte[] tmp = PlatformDependent.allocateUninitializedArray(length);
|
||||
byte[] tmp = ByteBufUtil.threadLocalTempArray(length);
|
||||
ByteBuffer tmpBuf = internalNioBuffer();
|
||||
tmpBuf.clear().position(index);
|
||||
tmpBuf.get(tmp);
|
||||
out.write(tmp);
|
||||
tmpBuf.get(tmp, 0, length);
|
||||
out.write(tmp, 0, length);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
@ -561,8 +561,8 @@ public class UnpooledDirectByteBuf extends AbstractReferenceCountedByteBuf {
|
||||
if (buffer.hasArray()) {
|
||||
return in.read(buffer.array(), buffer.arrayOffset() + index, length);
|
||||
} else {
|
||||
byte[] tmp = PlatformDependent.allocateUninitializedArray(length);
|
||||
int readBytes = in.read(tmp);
|
||||
byte[] tmp = ByteBufUtil.threadLocalTempArray(length);
|
||||
int readBytes = in.read(tmp, 0, length);
|
||||
if (readBytes <= 0) {
|
||||
return readBytes;
|
||||
}
|
||||
|
@ -584,7 +584,9 @@ final class UnsafeByteBufUtil {
|
||||
buf.checkIndex(index, length);
|
||||
if (length != 0) {
|
||||
int len = Math.min(length, ByteBufUtil.WRITE_CHUNK_SIZE);
|
||||
if (buf.alloc().isDirectBufferPooled()) {
|
||||
if (len <= ByteBufUtil.MAX_TL_ARRAY_LEN || !buf.alloc().isDirectBufferPooled()) {
|
||||
getBytes(addr, ByteBufUtil.threadLocalTempArray(length), 0, len, out, length);
|
||||
} else {
|
||||
// if direct buffers are pooled chances are good that heap buffers are pooled as well.
|
||||
ByteBuf tmpBuf = buf.alloc().heapBuffer(len);
|
||||
try {
|
||||
@ -594,9 +596,6 @@ final class UnsafeByteBufUtil {
|
||||
} finally {
|
||||
tmpBuf.release();
|
||||
}
|
||||
} else {
|
||||
byte[] tmp = PlatformDependent.allocateUninitializedArray(len);
|
||||
getBytes(addr, tmp, 0, len, out, length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user