1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.buffer;
17
18 import io.netty.util.internal.PlatformDependent;
19 import io.netty.util.internal.SystemPropertyUtil;
20 import io.netty.util.internal.UnstableApi;
21 import io.netty.util.internal.logging.InternalLogger;
22 import io.netty.util.internal.logging.InternalLoggerFactory;
23
24 import static io.netty.util.internal.PlatformDependent.javaVersion;
25
26
27
28
29
30
31
32
33
34 @UnstableApi
35 public final class AdaptiveByteBufAllocator extends AbstractByteBufAllocator
36 implements ByteBufAllocatorMetricProvider, ByteBufAllocatorMetric {
37 private static final InternalLogger logger = InternalLoggerFactory.getInstance(AdaptiveByteBufAllocator.class);
38 private static final boolean DEFAULT_USE_CACHED_MAGAZINES_FOR_NON_EVENT_LOOP_THREADS;
39
40 static {
41 DEFAULT_USE_CACHED_MAGAZINES_FOR_NON_EVENT_LOOP_THREADS = SystemPropertyUtil.getBoolean(
42 "io.netty.allocator.useCachedMagazinesForNonEventLoopThreads", false);
43 logger.debug("-Dio.netty.allocator.useCachedMagazinesForNonEventLoopThreads: {}",
44 DEFAULT_USE_CACHED_MAGAZINES_FOR_NON_EVENT_LOOP_THREADS);
45 }
46
47 private final AdaptiveAllocatorApi direct;
48 private final AdaptiveAllocatorApi heap;
49
50 public AdaptiveByteBufAllocator() {
51 this(!PlatformDependent.isExplicitNoPreferDirect());
52 }
53
54 public AdaptiveByteBufAllocator(boolean preferDirect) {
55 this(preferDirect, DEFAULT_USE_CACHED_MAGAZINES_FOR_NON_EVENT_LOOP_THREADS);
56 }
57
58 public AdaptiveByteBufAllocator(boolean preferDirect, boolean useCacheForNonEventLoopThreads) {
59 super(preferDirect);
60 if (javaVersion() < 8) {
61
62 throw new IllegalStateException("This allocator require Java 8 or newer.");
63 }
64 direct = new AdaptivePoolingAllocator(new DirectChunkAllocator(this), useCacheForNonEventLoopThreads);
65 heap = new AdaptivePoolingAllocator(new HeapChunkAllocator(this), useCacheForNonEventLoopThreads);
66 }
67
68 @Override
69 protected ByteBuf newHeapBuffer(int initialCapacity, int maxCapacity) {
70 return toLeakAwareBuffer(heap.allocate(initialCapacity, maxCapacity));
71 }
72
73 @Override
74 protected ByteBuf newDirectBuffer(int initialCapacity, int maxCapacity) {
75 return toLeakAwareBuffer(direct.allocate(initialCapacity, maxCapacity));
76 }
77
78 @Override
79 public boolean isDirectBufferPooled() {
80 return true;
81 }
82
83 @Override
84 public long usedHeapMemory() {
85 return heap.usedMemory();
86 }
87
88 @Override
89 public long usedDirectMemory() {
90 return direct.usedMemory();
91 }
92
93 @Override
94 public ByteBufAllocatorMetric metric() {
95 return this;
96 }
97
98 interface AdaptiveAllocatorApi {
99 ByteBuf allocate(int initialCapacity, int maxCapacity);
100 long usedMemory();
101 }
102
103 private static final class HeapChunkAllocator implements AdaptivePoolingAllocator.ChunkAllocator {
104 private final ByteBufAllocator allocator;
105
106 private HeapChunkAllocator(ByteBufAllocator allocator) {
107 this.allocator = allocator;
108 }
109
110 @Override
111 public AbstractByteBuf allocate(int initialCapacity, int maxCapacity) {
112 return PlatformDependent.hasUnsafe() ?
113 new UnpooledUnsafeHeapByteBuf(allocator, initialCapacity, maxCapacity) :
114 new UnpooledHeapByteBuf(allocator, initialCapacity, maxCapacity);
115 }
116 }
117
118 private static final class DirectChunkAllocator implements AdaptivePoolingAllocator.ChunkAllocator {
119 private final ByteBufAllocator allocator;
120
121 private DirectChunkAllocator(ByteBufAllocator allocator) {
122 this.allocator = allocator;
123 }
124
125 @Override
126 public AbstractByteBuf allocate(int initialCapacity, int maxCapacity) {
127 return PlatformDependent.hasUnsafe() ?
128 UnsafeByteBufUtil.newUnsafeDirectByteBuf(allocator, initialCapacity, maxCapacity) :
129 new UnpooledDirectByteBuf(allocator, initialCapacity, maxCapacity);
130 }
131 }
132 }