Add optimized version of setZero(...) / writeZero(...) for Unsafe*ByteBuf implementations

Motivation:

Unsafe offers a method to set memory to a specific value. This can be used to implement an optimized version of setZero(...) and writeZero(...)

Modifications:

Add implementation for all Unsafe*ByteBuf implementations.

Result:

Faster setZero(...) and writeZero(...)
This commit is contained in:
Norman Maurer 2016-05-23 14:53:31 +02:00
parent 339b512e70
commit db6b72da19
7 changed files with 119 additions and 0 deletions

View File

@ -371,4 +371,19 @@ final class PooledUnsafeDirectByteBuf extends PooledByteBuf<ByteBuffer> {
}
return super.newSwappedByteBuf();
}
@Override
public ByteBuf setZero(int index, int length) {
UnsafeByteBufUtil.setZero(this, addr(index), index, length);
return this;
}
@Override
public ByteBuf writeZero(int length) {
ensureWritable(length);
int wIndex = writerIndex;
setZero(wIndex, length);
writerIndex = wIndex + length;
return this;
}
}

View File

@ -128,6 +128,34 @@ final class PooledUnsafeHeapByteBuf extends PooledHeapByteBuf {
UnsafeByteBufUtil.setLongLE(memory, idx(index), value);
}
@Override
public ByteBuf setZero(int index, int length) {
if (PlatformDependent.javaVersion() >= 7) {
// Only do on java7+ as the needed Unsafe call was only added there.
_setZero(index, length);
return this;
}
return super.setZero(index, length);
}
@Override
public ByteBuf writeZero(int length) {
if (PlatformDependent.javaVersion() >= 7) {
// Only do on java7+ as the needed Unsafe call was only added there.
ensureWritable(length);
int wIndex = writerIndex;
_setZero(wIndex, length);
writerIndex = wIndex + length;
return this;
}
return super.writeZero(length);
}
private void _setZero(int index, int length) {
checkIndex(index, length);
UnsafeByteBufUtil.setZero(memory, idx(index), length);
}
@Override
@Deprecated
protected SwappedByteBuf newSwappedByteBuf() {

View File

@ -503,4 +503,19 @@ public class UnpooledUnsafeDirectByteBuf extends AbstractReferenceCountedByteBuf
}
return super.newSwappedByteBuf();
}
@Override
public ByteBuf setZero(int index, int length) {
UnsafeByteBufUtil.setZero(this, addr(index), index, length);
return this;
}
@Override
public ByteBuf writeZero(int length) {
ensureWritable(length);
int wIndex = writerIndex;
setZero(wIndex, length);
writerIndex = wIndex + length;
return this;
}
}

View File

@ -236,6 +236,34 @@ final class UnpooledUnsafeHeapByteBuf extends UnpooledHeapByteBuf {
UnsafeByteBufUtil.setLongLE(array, index, value);
}
@Override
public ByteBuf setZero(int index, int length) {
if (PlatformDependent.javaVersion() >= 7) {
// Only do on java7+ as the needed Unsafe call was only added there.
_setZero(index, length);
return this;
}
return super.setZero(index, length);
}
@Override
public ByteBuf writeZero(int length) {
if (PlatformDependent.javaVersion() >= 7) {
// Only do on java7+ as the needed Unsafe call was only added there.
ensureWritable(length);
int wIndex = writerIndex;
_setZero(wIndex, length);
writerIndex = wIndex + length;
return this;
}
return super.writeZero(length);
}
private void _setZero(int index, int length) {
checkIndex(index, length);
UnsafeByteBufUtil.setZero(array, index, length);
}
@Override
@Deprecated
protected SwappedByteBuf newSwappedByteBuf() {

View File

@ -33,6 +33,7 @@ import static io.netty.util.internal.PlatformDependent.BIG_ENDIAN_NATIVE_ORDER;
*/
final class UnsafeByteBufUtil {
private static final boolean UNALIGNED = PlatformDependent.isUnaligned();
private static final byte ZERO = 0;
static byte getByte(long address) {
return PlatformDependent.getByte(address);
@ -451,6 +452,13 @@ final class UnsafeByteBufUtil {
}
}
static void setZero(byte[] array, int index, int length) {
if (length == 0) {
return;
}
PlatformDependent.setMemory(array, index, length, ZERO);
}
static ByteBuf copy(AbstractByteBuf buf, long addr, int index, int length) {
buf.checkIndex(index, length);
ByteBuf copy = buf.alloc().directBuffer(length, buf.maxCapacity());
@ -602,5 +610,14 @@ final class UnsafeByteBufUtil {
}
}
static void setZero(AbstractByteBuf buf, long addr, int index, int length) {
if (length == 0) {
return;
}
buf.checkIndex(index, length);
PlatformDependent.setMemory(addr, length, ZERO);
}
private UnsafeByteBufUtil() { }
}

View File

@ -496,6 +496,14 @@ public final class PlatformDependent {
PlatformDependent0.copyMemory(null, srcAddr, dst, BYTE_ARRAY_BASE_OFFSET + dstIndex, length);
}
public static void setMemory(byte[] dst, int dstIndex, long bytes, byte value) {
PlatformDependent0.setMemory(dst, BYTE_ARRAY_BASE_OFFSET + dstIndex, bytes, value);
}
public static void setMemory(long address, long bytes, byte value) {
PlatformDependent0.setMemory(address, bytes, value);
}
/**
* Compare two {@code byte} arrays for equality. For performance reasons no bounds checking on the
* parameters is performed.

View File

@ -322,6 +322,14 @@ final class PlatformDependent0 {
}
}
static void setMemory(long address, long bytes, byte value) {
UNSAFE.setMemory(address, bytes, value);
}
static void setMemory(Object o, long offset, long bytes, byte value) {
UNSAFE.setMemory(o, offset, bytes, value);
}
static boolean equals(byte[] bytes1, int startPos1, byte[] bytes2, int startPos2, int length) {
if (length == 0) {
return true;