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