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