Ensure Unsafe buffer implementations are used when sun.misc.Unsafe is present
Motivation: When sun.misc.Unsafe is present we want to use *Unsafe*ByteBuf implementations. We missed to do so in PooledByteBufAllocator when the heapArena is null. Modifications: - Correctly use UnpooledUnsafeHeapByteBuf - Add unit tests Result: Use most optimal ByteBuf implementation.
This commit is contained in:
parent
ad03adcb7b
commit
2935878eee
@ -305,11 +305,13 @@ public class PooledByteBufAllocator extends AbstractByteBufAllocator {
|
|||||||
PoolThreadCache cache = threadCache.get();
|
PoolThreadCache cache = threadCache.get();
|
||||||
PoolArena<byte[]> heapArena = cache.heapArena;
|
PoolArena<byte[]> heapArena = cache.heapArena;
|
||||||
|
|
||||||
ByteBuf buf;
|
final ByteBuf buf;
|
||||||
if (heapArena != null) {
|
if (heapArena != null) {
|
||||||
buf = heapArena.allocate(cache, initialCapacity, maxCapacity);
|
buf = heapArena.allocate(cache, initialCapacity, maxCapacity);
|
||||||
} else {
|
} else {
|
||||||
buf = new UnpooledHeapByteBuf(this, initialCapacity, maxCapacity);
|
buf = PlatformDependent.hasUnsafe() ?
|
||||||
|
new UnpooledUnsafeHeapByteBuf(this, initialCapacity, maxCapacity) :
|
||||||
|
new UnpooledHeapByteBuf(this, initialCapacity, maxCapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
return toLeakAwareBuffer(buf);
|
return toLeakAwareBuffer(buf);
|
||||||
@ -320,15 +322,13 @@ public class PooledByteBufAllocator extends AbstractByteBufAllocator {
|
|||||||
PoolThreadCache cache = threadCache.get();
|
PoolThreadCache cache = threadCache.get();
|
||||||
PoolArena<ByteBuffer> directArena = cache.directArena;
|
PoolArena<ByteBuffer> directArena = cache.directArena;
|
||||||
|
|
||||||
ByteBuf buf;
|
final ByteBuf buf;
|
||||||
if (directArena != null) {
|
if (directArena != null) {
|
||||||
buf = directArena.allocate(cache, initialCapacity, maxCapacity);
|
buf = directArena.allocate(cache, initialCapacity, maxCapacity);
|
||||||
} else {
|
} else {
|
||||||
if (PlatformDependent.hasUnsafe()) {
|
buf = PlatformDependent.hasUnsafe() ?
|
||||||
buf = UnsafeByteBufUtil.newUnsafeDirectByteBuf(this, initialCapacity, maxCapacity);
|
UnsafeByteBufUtil.newUnsafeDirectByteBuf(this, initialCapacity, maxCapacity) :
|
||||||
} else {
|
new UnpooledDirectByteBuf(this, initialCapacity, maxCapacity);
|
||||||
buf = new UnpooledDirectByteBuf(this, initialCapacity, maxCapacity);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return toLeakAwareBuffer(buf);
|
return toLeakAwareBuffer(buf);
|
||||||
|
@ -17,11 +17,17 @@ package io.netty.buffer;
|
|||||||
|
|
||||||
import io.netty.util.internal.PlatformDependent;
|
import io.netty.util.internal.PlatformDependent;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
public abstract class AbstractByteBufAllocatorTest extends ByteBufAllocatorTest {
|
public abstract class AbstractByteBufAllocatorTest extends ByteBufAllocatorTest {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected abstract AbstractByteBufAllocator newAllocator(boolean preferDirect);
|
protected abstract AbstractByteBufAllocator newAllocator(boolean preferDirect);
|
||||||
|
|
||||||
|
protected abstract AbstractByteBufAllocator newUnpooledAllocator();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isDirectExpected(boolean preferDirect) {
|
protected boolean isDirectExpected(boolean preferDirect) {
|
||||||
return preferDirect && PlatformDependent.hasUnsafe();
|
return preferDirect && PlatformDependent.hasUnsafe();
|
||||||
@ -36,4 +42,23 @@ public abstract class AbstractByteBufAllocatorTest extends ByteBufAllocatorTest
|
|||||||
protected final int defaultMaxComponents() {
|
protected final int defaultMaxComponents() {
|
||||||
return AbstractByteBufAllocator.DEFAULT_MAX_COMPONENTS;
|
return AbstractByteBufAllocator.DEFAULT_MAX_COMPONENTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUnsafeHeapBufferAndUnsafeDirectBuffer() {
|
||||||
|
AbstractByteBufAllocator allocator = newUnpooledAllocator();
|
||||||
|
ByteBuf directBuffer = allocator.directBuffer();
|
||||||
|
assertInstanceOf(directBuffer,
|
||||||
|
PlatformDependent.hasUnsafe() ? UnpooledUnsafeDirectByteBuf.class : UnpooledDirectByteBuf.class);
|
||||||
|
directBuffer.release();
|
||||||
|
|
||||||
|
ByteBuf heapBuffer = allocator.heapBuffer();
|
||||||
|
assertInstanceOf(heapBuffer,
|
||||||
|
PlatformDependent.hasUnsafe() ? UnpooledUnsafeHeapByteBuf.class : UnpooledHeapByteBuf.class);
|
||||||
|
heapBuffer.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static void assertInstanceOf(ByteBuf buffer, Class<? extends ByteBuf> clazz) {
|
||||||
|
// Unwrap if needed
|
||||||
|
assertTrue(clazz.isInstance(buffer instanceof SimpleLeakAwareByteBuf ? buffer.unwrap() : buffer));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ package io.netty.buffer;
|
|||||||
|
|
||||||
import io.netty.util.concurrent.FastThreadLocal;
|
import io.netty.util.concurrent.FastThreadLocal;
|
||||||
import io.netty.util.concurrent.FastThreadLocalThread;
|
import io.netty.util.concurrent.FastThreadLocalThread;
|
||||||
|
import io.netty.util.internal.PlatformDependent;
|
||||||
import io.netty.util.internal.SystemPropertyUtil;
|
import io.netty.util.internal.SystemPropertyUtil;
|
||||||
import org.junit.Assume;
|
import org.junit.Assume;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@ -43,6 +44,25 @@ public class PooledByteBufAllocatorTest extends AbstractByteBufAllocatorTest {
|
|||||||
return new PooledByteBufAllocator(preferDirect);
|
return new PooledByteBufAllocator(preferDirect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected AbstractByteBufAllocator newUnpooledAllocator() {
|
||||||
|
return new PooledByteBufAllocator(0, 0, 8192, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPooledUnsafeHeapBufferAndUnsafeDirectBuffer() {
|
||||||
|
AbstractByteBufAllocator allocator = newAllocator(true);
|
||||||
|
ByteBuf directBuffer = allocator.directBuffer();
|
||||||
|
assertInstanceOf(directBuffer,
|
||||||
|
PlatformDependent.hasUnsafe() ? PooledUnsafeDirectByteBuf.class : PooledDirectByteBuf.class);
|
||||||
|
directBuffer.release();
|
||||||
|
|
||||||
|
ByteBuf heapBuffer = allocator.heapBuffer();
|
||||||
|
assertInstanceOf(heapBuffer,
|
||||||
|
PlatformDependent.hasUnsafe() ? PooledUnsafeHeapByteBuf.class : PooledHeapByteBuf.class);
|
||||||
|
heapBuffer.release();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testArenaMetricsNoCache() {
|
public void testArenaMetricsNoCache() {
|
||||||
testArenaMetrics0(new PooledByteBufAllocator(true, 2, 2, 8192, 11, 0, 0, 0), 100, 0, 100, 100);
|
testArenaMetrics0(new PooledByteBufAllocator(true, 2, 2, 8192, 11, 0, 0, 0), 100, 0, 100, 100);
|
||||||
|
@ -21,4 +21,9 @@ public class UnpooledByteBufAllocatorTest extends AbstractByteBufAllocatorTest {
|
|||||||
protected AbstractByteBufAllocator newAllocator(boolean preferDirect) {
|
protected AbstractByteBufAllocator newAllocator(boolean preferDirect) {
|
||||||
return new UnpooledByteBufAllocator(preferDirect);
|
return new UnpooledByteBufAllocator(preferDirect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected AbstractByteBufAllocator newUnpooledAllocator() {
|
||||||
|
return new UnpooledByteBufAllocator(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user