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:
Matteo Merli 2015-10-18 21:59:26 -07:00 committed by Norman Maurer
parent 5a6238ed4c
commit 27c68647df
2 changed files with 55 additions and 38 deletions

View File

@ -148,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;
}
@ -279,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;
}

View File

@ -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;
}