In (Pooled|Unpooled)UnsafeDirectByteBuf copy memory directly to and from ByteBuffer
Motivation: When moving bytes between a PooledUnsafeDirectByteBuf or an UnpooledUnsafeDirectByteBuf and a ByteBuffer, a temp ByteBuffer is allocated and will need to be GCed. This is a common case since a ByteBuffer is always needed when reading/writing on a file, for example. Modifications: Use PlatformDependent.copyMemory() to avoid the need for the temp ByteBuffer Result: No temp ByteBuffer allocated and GCed.
This commit is contained in:
parent
3bc4d2330a
commit
a6324758b8
@ -16,7 +16,6 @@
|
||||
|
||||
package io.netty.buffer;
|
||||
|
||||
import io.netty.buffer.PooledByteBufAllocator.PoolThreadLocalCache;
|
||||
import io.netty.util.Recycler;
|
||||
import io.netty.util.internal.PlatformDependent;
|
||||
|
||||
@ -149,29 +148,30 @@ final class PooledUnsafeDirectByteBuf extends PooledByteBuf<ByteBuffer> {
|
||||
|
||||
@Override
|
||||
public ByteBuf getBytes(int index, ByteBuffer dst) {
|
||||
getBytes(index, dst, false);
|
||||
return this;
|
||||
}
|
||||
|
||||
private void getBytes(int index, ByteBuffer dst, boolean internal) {
|
||||
checkIndex(index);
|
||||
int bytesToCopy = Math.min(capacity() - index, dst.remaining());
|
||||
ByteBuffer tmpBuf;
|
||||
if (internal) {
|
||||
tmpBuf = internalNioBuffer();
|
||||
} else {
|
||||
tmpBuf = memory.duplicate();
|
||||
if (bytesToCopy == 0) {
|
||||
return this;
|
||||
}
|
||||
index = idx(index);
|
||||
tmpBuf.clear().position(index).limit(index + bytesToCopy);
|
||||
dst.put(tmpBuf);
|
||||
|
||||
if (dst.isDirect()) {
|
||||
// Copy to direct memory
|
||||
long dstAddress = PlatformDependent.directBufferAddress(dst);
|
||||
PlatformDependent.copyMemory(addr(index), dstAddress + dst.position(), bytesToCopy);
|
||||
} else {
|
||||
// Copy to array
|
||||
PlatformDependent.copyMemory(addr(index), dst.array(), dst.arrayOffset() + dst.position(), bytesToCopy);
|
||||
}
|
||||
|
||||
dst.position(dst.position() + bytesToCopy);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf readBytes(ByteBuffer dst) {
|
||||
int length = dst.remaining();
|
||||
checkReadableBytes(length);
|
||||
getBytes(readerIndex, dst, true);
|
||||
getBytes(readerIndex, dst);
|
||||
readerIndex += length;
|
||||
return this;
|
||||
}
|
||||
@ -280,14 +280,21 @@ final class PooledUnsafeDirectByteBuf extends PooledByteBuf<ByteBuffer> {
|
||||
@Override
|
||||
public ByteBuf setBytes(int index, ByteBuffer src) {
|
||||
checkIndex(index, src.remaining());
|
||||
ByteBuffer tmpBuf = internalNioBuffer();
|
||||
if (src == tmpBuf) {
|
||||
src = src.duplicate();
|
||||
|
||||
int length = src.remaining();
|
||||
if (length == 0) {
|
||||
return this;
|
||||
}
|
||||
|
||||
index = idx(index);
|
||||
tmpBuf.clear().position(index).limit(index + src.remaining());
|
||||
tmpBuf.put(src);
|
||||
if (src.isDirect()) {
|
||||
// Copy from direct memory
|
||||
long srcAddress = PlatformDependent.directBufferAddress(src);
|
||||
PlatformDependent.copyMemory(srcAddress + src.position(), addr(index), src.remaining());
|
||||
} else {
|
||||
// Copy from array
|
||||
PlatformDependent.copyMemory(src.array(), src.arrayOffset() + src.position(), addr(index), length);
|
||||
}
|
||||
src.position(src.position() + length);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -285,32 +285,34 @@ public class UnpooledUnsafeDirectByteBuf extends AbstractReferenceCountedByteBuf
|
||||
|
||||
@Override
|
||||
public ByteBuf getBytes(int index, ByteBuffer dst) {
|
||||
getBytes(index, dst, false);
|
||||
return this;
|
||||
}
|
||||
|
||||
private void getBytes(int index, ByteBuffer dst, boolean internal) {
|
||||
checkIndex(index);
|
||||
if (dst == null) {
|
||||
throw new NullPointerException("dst");
|
||||
}
|
||||
|
||||
int bytesToCopy = Math.min(capacity() - index, dst.remaining());
|
||||
ByteBuffer tmpBuf;
|
||||
if (internal) {
|
||||
tmpBuf = internalNioBuffer();
|
||||
} else {
|
||||
tmpBuf = buffer.duplicate();
|
||||
if (bytesToCopy == 0) {
|
||||
return this;
|
||||
}
|
||||
tmpBuf.clear().position(index).limit(index + bytesToCopy);
|
||||
dst.put(tmpBuf);
|
||||
|
||||
if (dst.isDirect()) {
|
||||
// Copy to direct memory
|
||||
long dstAddress = PlatformDependent.directBufferAddress(dst);
|
||||
PlatformDependent.copyMemory(addr(index), dstAddress + dst.position(), bytesToCopy);
|
||||
} else {
|
||||
// Copy to array
|
||||
PlatformDependent.copyMemory(addr(index), dst.array(), dst.arrayOffset() + dst.position(), bytesToCopy);
|
||||
}
|
||||
|
||||
dst.position(dst.position() + bytesToCopy);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf readBytes(ByteBuffer dst) {
|
||||
int length = dst.remaining();
|
||||
checkReadableBytes(length);
|
||||
getBytes(readerIndex, dst, true);
|
||||
getBytes(readerIndex, dst);
|
||||
readerIndex += length;
|
||||
return this;
|
||||
}
|
||||
@ -377,13 +379,20 @@ public class UnpooledUnsafeDirectByteBuf extends AbstractReferenceCountedByteBuf
|
||||
@Override
|
||||
public ByteBuf setBytes(int index, ByteBuffer src) {
|
||||
ensureAccessible();
|
||||
ByteBuffer tmpBuf = internalNioBuffer();
|
||||
if (src == tmpBuf) {
|
||||
src = src.duplicate();
|
||||
int length = src.remaining();
|
||||
if (length == 0) {
|
||||
return this;
|
||||
}
|
||||
|
||||
tmpBuf.clear().position(index).limit(index + src.remaining());
|
||||
tmpBuf.put(src);
|
||||
if (src.isDirect()) {
|
||||
// Copy from direct memory
|
||||
long srcAddress = PlatformDependent.directBufferAddress(src);
|
||||
PlatformDependent.copyMemory(srcAddress + src.position(), addr(index), src.remaining());
|
||||
} else {
|
||||
// Copy from array
|
||||
PlatformDependent.copyMemory(src.array(), src.arrayOffset() + src.position(), addr(index), length);
|
||||
}
|
||||
src.position(src.position() + length);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user