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