From 27c68647df61562984b279d7e2c2d21b56d4075e Mon Sep 17 00:00:00 2001 From: Matteo Merli Date: Sun, 18 Oct 2015 21:59:26 -0700 Subject: [PATCH] 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. --- .../buffer/PooledUnsafeDirectByteBuf.java | 48 +++++++++++-------- .../buffer/UnpooledUnsafeDirectByteBuf.java | 45 ++++++++++------- 2 files changed, 55 insertions(+), 38 deletions(-) diff --git a/buffer/src/main/java/io/netty/buffer/PooledUnsafeDirectByteBuf.java b/buffer/src/main/java/io/netty/buffer/PooledUnsafeDirectByteBuf.java index 96f2792496..d1a39a7256 100644 --- a/buffer/src/main/java/io/netty/buffer/PooledUnsafeDirectByteBuf.java +++ b/buffer/src/main/java/io/netty/buffer/PooledUnsafeDirectByteBuf.java @@ -148,29 +148,30 @@ final class PooledUnsafeDirectByteBuf extends PooledByteBuf { @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 { @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; } diff --git a/buffer/src/main/java/io/netty/buffer/UnpooledUnsafeDirectByteBuf.java b/buffer/src/main/java/io/netty/buffer/UnpooledUnsafeDirectByteBuf.java index 065deb9907..809b2df037 100644 --- a/buffer/src/main/java/io/netty/buffer/UnpooledUnsafeDirectByteBuf.java +++ b/buffer/src/main/java/io/netty/buffer/UnpooledUnsafeDirectByteBuf.java @@ -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; }