Change ByteBufAllocator.buffer() to allocate a direct buffer only when the platform can handle a direct buffer reliably

- Rename directbyDefault to preferDirect
 - Add a system property 'io.netty.prederDirect' to allow a user from changing the preference on launch-time
 - Merge UnpooledByteBufAllocator.DEFAULT_BY_* to DEFAULT
This commit is contained in:
Trustin Lee 2013-03-05 17:55:24 +09:00
parent a8a7c4f576
commit 8d88acb4a7
9 changed files with 42 additions and 44 deletions

View File

@ -16,6 +16,8 @@
package io.netty.buffer;
import io.netty.util.internal.PlatformDependent;
/**
* Skeltal {@link ByteBufAllocator} implementation to extend.
*/
@ -34,10 +36,11 @@ public abstract class AbstractByteBufAllocator implements ByteBufAllocator {
/**
* Create new instance
*
* @param directByDefault {@code true} if direct buffers should be used by default.
* @param preferDirect {@code true} if {@link #buffer(int)} should try to allocate a direct buffer rather than
* a heap buffer
*/
protected AbstractByteBufAllocator(boolean directByDefault) {
this.directByDefault = directByDefault;
protected AbstractByteBufAllocator(boolean preferDirect) {
directByDefault = preferDirect && PlatformDependent.hasUnsafe();
emptyBuf = new UnpooledHeapByteBuf(this, 0, 0);
}
@ -65,6 +68,14 @@ public abstract class AbstractByteBufAllocator implements ByteBufAllocator {
return heapBuffer(initialCapacity, maxCapacity);
}
@Override
public ByteBuf ioBuffer() {
if (PlatformDependent.hasUnsafe()) {
return directBuffer(0);
}
return heapBuffer(0);
}
@Override
public ByteBuf heapBuffer() {
return heapBuffer(256, Integer.MAX_VALUE);

View File

@ -55,7 +55,7 @@ public final class EmptyByteBuf implements ByteBuf {
@Override
public ByteBufAllocator alloc() {
return UnpooledByteBufAllocator.HEAP_BY_DEFAULT;
return UnpooledByteBufAllocator.DEFAULT;
}
@Override

View File

@ -16,6 +16,7 @@
package io.netty.buffer;
import io.netty.util.internal.PlatformDependent;
import io.netty.util.internal.StringUtil;
import java.nio.ByteBuffer;
@ -31,7 +32,8 @@ public class PooledByteBufAllocator extends AbstractByteBufAllocator {
private static final int MIN_PAGE_SIZE = 4096;
private static final int MAX_CHUNK_SIZE = (int) (((long) Integer.MAX_VALUE + 1) / 2);
public static final PooledByteBufAllocator DEFAULT = new PooledByteBufAllocator();
public static final PooledByteBufAllocator DEFAULT =
new PooledByteBufAllocator(PlatformDependent.directBufferPreferred());
private final PoolArena<byte[]>[] heapArenas;
private final PoolArena<ByteBuffer>[] directArenas;
@ -49,8 +51,8 @@ public class PooledByteBufAllocator extends AbstractByteBufAllocator {
this(false);
}
public PooledByteBufAllocator(boolean directByDefault) {
this(directByDefault, DEFAULT_NUM_HEAP_ARENA, DEFAULT_NUM_DIRECT_ARENA, DEFAULT_PAGE_SIZE, DEFAULT_MAX_ORDER);
public PooledByteBufAllocator(boolean preferDirect) {
this(preferDirect, DEFAULT_NUM_HEAP_ARENA, DEFAULT_NUM_DIRECT_ARENA, DEFAULT_PAGE_SIZE, DEFAULT_MAX_ORDER);
}
public PooledByteBufAllocator(int nHeapArena, int nDirectArena, int pageSize, int maxOrder) {
@ -141,11 +143,6 @@ public class PooledByteBufAllocator extends AbstractByteBufAllocator {
return cache.directArena.allocate(cache, initialCapacity, maxCapacity);
}
@Override
public ByteBuf ioBuffer() {
return directBuffer(0);
}
public String toString() {
StringBuilder buf = new StringBuilder();
buf.append(heapArenas.length);

View File

@ -75,7 +75,7 @@ import java.util.Queue;
*/
public final class Unpooled {
private static final ByteBufAllocator ALLOC = UnpooledByteBufAllocator.HEAP_BY_DEFAULT;
private static final ByteBufAllocator ALLOC = UnpooledByteBufAllocator.DEFAULT;
/**
* Big endian byte order.

View File

@ -22,11 +22,11 @@ import io.netty.util.internal.PlatformDependent;
*/
public final class UnpooledByteBufAllocator extends AbstractByteBufAllocator {
public static final UnpooledByteBufAllocator HEAP_BY_DEFAULT = new UnpooledByteBufAllocator(false);
public static final UnpooledByteBufAllocator DIRECT_BY_DEFAULT = new UnpooledByteBufAllocator(true);
public static final UnpooledByteBufAllocator DEFAULT =
new UnpooledByteBufAllocator(PlatformDependent.directBufferPreferred());
private UnpooledByteBufAllocator(boolean directByDefault) {
super(directByDefault);
public UnpooledByteBufAllocator(boolean preferDirect) {
super(preferDirect);
}
@Override
@ -38,12 +38,4 @@ public final class UnpooledByteBufAllocator extends AbstractByteBufAllocator {
protected ByteBuf newDirectBuffer(int initialCapacity, int maxCapacity) {
return new UnpooledDirectByteBuf(this, initialCapacity, maxCapacity);
}
@Override
public ByteBuf ioBuffer() {
if (PlatformDependent.hasUnsafe()) {
return directBuffer(0);
}
return heapBuffer(0);
}
}

View File

@ -45,6 +45,6 @@ public class BigEndianHeapByteBufTest extends AbstractByteBufTest {
@Test(expected = NullPointerException.class)
public void shouldNotAllowNullInConstructor2() {
new UnpooledHeapByteBuf(UnpooledByteBufAllocator.HEAP_BY_DEFAULT, null, 0);
new UnpooledHeapByteBuf(UnpooledByteBufAllocator.DEFAULT, null, 0);
}
}

View File

@ -49,6 +49,9 @@ public final class PlatformDependent {
private static final boolean HAS_UNSAFE = hasUnsafe0();
private static final boolean CAN_USE_CHM_V8 = HAS_UNSAFE && JAVA_VERSION < 8;
private static final boolean DIRECT_BUFFER_PREFERRED =
HAS_UNSAFE && SystemPropertyUtil.getBoolean("io.netty.preferDirect", false);
private static final long ARRAY_BASE_OFFSET = arrayBaseOffset0();
private static final boolean HAS_JAVASSIST = hasJavassist0();
@ -97,6 +100,14 @@ public final class PlatformDependent {
return HAS_UNSAFE;
}
/**
* Returns {@code true} if the platform has reliable low-level direct buffer access API and a user specified
* {@code -Dio.netty.preferDirect} option.
*/
public static boolean directBufferPreferred() {
return DIRECT_BUFFER_PREFERRED;
}
/**
* Returns {@code true} if and only if Javassist is available.
*/
@ -160,13 +171,6 @@ public final class PlatformDependent {
}
}
/**
* Try to allocate a new direct {@link ByteBuffer} using the best available allocator.
*/
public static ByteBuffer newDirectBuffer(int capacity) {
return PlatformDependent0.newDirectBuffer(capacity);
}
/**
* Try to deallocate the specified direct {@link ByteBuffer}. Please note this method does nothing if
* the current platform does not support this operation or the specified buffer is not a direct buffer.

View File

@ -119,14 +119,6 @@ final class PlatformDependent0 {
return UNSAFE != null;
}
static ByteBuffer newDirectBuffer(int capacity) {
if (hasUnsafe()) {
return ByteBuffer.allocateDirect(capacity);
} else {
throw new Error("refusing to create a direct buffer without proper access to the low-level API");
}
}
static void freeDirectBuffer(ByteBuffer buffer) {
Cleaner cleaner;
try {

View File

@ -28,7 +28,9 @@ import java.util.Deque;
public class ByteBufAllocatorBenchmark extends DefaultBenchmark {
private static final ByteBufAllocator POOLED_ALLOCATOR_HEAP = PooledByteBufAllocator.DEFAULT;
private static final ByteBufAllocator UNPOOLED_ALLOCATOR_HEAP = new UnpooledByteBufAllocator(false);
private static final ByteBufAllocator UNPOOLED_ALLOCATOR_DIRECT = new UnpooledByteBufAllocator(true);
private static final ByteBufAllocator POOLED_ALLOCATOR_HEAP = new PooledByteBufAllocator(false);
private static final ByteBufAllocator POOLED_ALLOCATOR_DIRECT = new PooledByteBufAllocator(true);
@Param({"0", "256", "1024", "4096", "16384", "65536"})
@ -71,13 +73,13 @@ public class ByteBufAllocatorBenchmark extends DefaultBenchmark {
UNPOOLED_HEAP {
@Override
ByteBufAllocator alloc() {
return UnpooledByteBufAllocator.HEAP_BY_DEFAULT;
return UNPOOLED_ALLOCATOR_HEAP;
}
},
UNPOOLED_DIRECT {
@Override
ByteBufAllocator alloc() {
return UnpooledByteBufAllocator.DIRECT_BY_DEFAULT;
return UNPOOLED_ALLOCATOR_DIRECT;
}
},
POOLED_HEAP {