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