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.LongCounter;
19 import io.netty.util.internal.PlatformDependent;
20 import io.netty.util.internal.StringUtil;
21
22 import java.nio.ByteBuffer;
23
24
25
26
27 public final class UnpooledByteBufAllocator extends AbstractByteBufAllocator implements ByteBufAllocatorMetricProvider {
28
29 private final UnpooledByteBufAllocatorMetric metric = new UnpooledByteBufAllocatorMetric();
30 private final boolean disableLeakDetector;
31 private final boolean noCleaner;
32
33
34
35
36 public static final UnpooledByteBufAllocator DEFAULT =
37 new UnpooledByteBufAllocator(PlatformDependent.directBufferPreferred());
38
39
40
41
42
43
44
45 public UnpooledByteBufAllocator(boolean preferDirect) {
46 this(preferDirect, false);
47 }
48
49
50
51
52
53
54
55
56
57
58 public UnpooledByteBufAllocator(boolean preferDirect, boolean disableLeakDetector) {
59 this(preferDirect, disableLeakDetector, PlatformDependent.useDirectBufferNoCleaner());
60 }
61
62
63
64
65
66
67
68
69
70
71
72
73 public UnpooledByteBufAllocator(boolean preferDirect, boolean disableLeakDetector, boolean tryNoCleaner) {
74 super(preferDirect);
75 this.disableLeakDetector = disableLeakDetector;
76 noCleaner = tryNoCleaner && PlatformDependent.hasUnsafe()
77 && PlatformDependent.hasDirectBufferNoCleanerConstructor();
78 }
79
80 @Override
81 protected ByteBuf newHeapBuffer(int initialCapacity, int maxCapacity) {
82 return PlatformDependent.hasUnsafe() ?
83 new InstrumentedUnpooledUnsafeHeapByteBuf(this, initialCapacity, maxCapacity) :
84 new InstrumentedUnpooledHeapByteBuf(this, initialCapacity, maxCapacity);
85 }
86
87 @Override
88 protected ByteBuf newDirectBuffer(int initialCapacity, int maxCapacity) {
89 final ByteBuf buf;
90 if (PlatformDependent.hasUnsafe()) {
91 buf = noCleaner ? new InstrumentedUnpooledUnsafeNoCleanerDirectByteBuf(this, initialCapacity, maxCapacity) :
92 new InstrumentedUnpooledUnsafeDirectByteBuf(this, initialCapacity, maxCapacity);
93 } else {
94 buf = new InstrumentedUnpooledDirectByteBuf(this, initialCapacity, maxCapacity);
95 }
96 return disableLeakDetector ? buf : toLeakAwareBuffer(buf);
97 }
98
99 @Override
100 public CompositeByteBuf compositeHeapBuffer(int maxNumComponents) {
101 CompositeByteBuf buf = new CompositeByteBuf(this, false, maxNumComponents);
102 return disableLeakDetector ? buf : toLeakAwareBuffer(buf);
103 }
104
105 @Override
106 public CompositeByteBuf compositeDirectBuffer(int maxNumComponents) {
107 CompositeByteBuf buf = new CompositeByteBuf(this, true, maxNumComponents);
108 return disableLeakDetector ? buf : toLeakAwareBuffer(buf);
109 }
110
111 @Override
112 public boolean isDirectBufferPooled() {
113 return false;
114 }
115
116 @Override
117 public ByteBufAllocatorMetric metric() {
118 return metric;
119 }
120
121 void incrementDirect(int amount) {
122 metric.directCounter.add(amount);
123 }
124
125 void decrementDirect(int amount) {
126 metric.directCounter.add(-amount);
127 }
128
129 void incrementHeap(int amount) {
130 metric.heapCounter.add(amount);
131 }
132
133 void decrementHeap(int amount) {
134 metric.heapCounter.add(-amount);
135 }
136
137 private static final class InstrumentedUnpooledUnsafeHeapByteBuf extends UnpooledUnsafeHeapByteBuf {
138 InstrumentedUnpooledUnsafeHeapByteBuf(UnpooledByteBufAllocator alloc, int initialCapacity, int maxCapacity) {
139 super(alloc, initialCapacity, maxCapacity);
140 }
141
142 @Override
143 byte[] allocateArray(int initialCapacity) {
144 byte[] bytes = super.allocateArray(initialCapacity);
145 ((UnpooledByteBufAllocator) alloc()).incrementHeap(bytes.length);
146 return bytes;
147 }
148
149 @Override
150 void freeArray(byte[] array) {
151 int length = array.length;
152 super.freeArray(array);
153 ((UnpooledByteBufAllocator) alloc()).decrementHeap(length);
154 }
155 }
156
157 private static final class InstrumentedUnpooledHeapByteBuf extends UnpooledHeapByteBuf {
158 InstrumentedUnpooledHeapByteBuf(UnpooledByteBufAllocator alloc, int initialCapacity, int maxCapacity) {
159 super(alloc, initialCapacity, maxCapacity);
160 }
161
162 @Override
163 byte[] allocateArray(int initialCapacity) {
164 byte[] bytes = super.allocateArray(initialCapacity);
165 ((UnpooledByteBufAllocator) alloc()).incrementHeap(bytes.length);
166 return bytes;
167 }
168
169 @Override
170 void freeArray(byte[] array) {
171 int length = array.length;
172 super.freeArray(array);
173 ((UnpooledByteBufAllocator) alloc()).decrementHeap(length);
174 }
175 }
176
177 private static final class InstrumentedUnpooledUnsafeNoCleanerDirectByteBuf
178 extends UnpooledUnsafeNoCleanerDirectByteBuf {
179 InstrumentedUnpooledUnsafeNoCleanerDirectByteBuf(
180 UnpooledByteBufAllocator alloc, int initialCapacity, int maxCapacity) {
181 super(alloc, initialCapacity, maxCapacity);
182 }
183
184 @Override
185 protected ByteBuffer allocateDirect(int initialCapacity) {
186 ByteBuffer buffer = super.allocateDirect(initialCapacity);
187 ((UnpooledByteBufAllocator) alloc()).incrementDirect(buffer.capacity());
188 return buffer;
189 }
190
191 @Override
192 ByteBuffer reallocateDirect(ByteBuffer oldBuffer, int initialCapacity) {
193 int capacity = oldBuffer.capacity();
194 ByteBuffer buffer = super.reallocateDirect(oldBuffer, initialCapacity);
195 ((UnpooledByteBufAllocator) alloc()).incrementDirect(buffer.capacity() - capacity);
196 return buffer;
197 }
198
199 @Override
200 protected void freeDirect(ByteBuffer buffer) {
201 int capacity = buffer.capacity();
202 super.freeDirect(buffer);
203 ((UnpooledByteBufAllocator) alloc()).decrementDirect(capacity);
204 }
205 }
206
207 private static final class InstrumentedUnpooledUnsafeDirectByteBuf extends UnpooledUnsafeDirectByteBuf {
208 InstrumentedUnpooledUnsafeDirectByteBuf(
209 UnpooledByteBufAllocator alloc, int initialCapacity, int maxCapacity) {
210 super(alloc, initialCapacity, maxCapacity);
211 }
212
213 @Override
214 protected ByteBuffer allocateDirect(int initialCapacity) {
215 ByteBuffer buffer = super.allocateDirect(initialCapacity);
216 ((UnpooledByteBufAllocator) alloc()).incrementDirect(buffer.capacity());
217 return buffer;
218 }
219
220 @Override
221 protected void freeDirect(ByteBuffer buffer) {
222 int capacity = buffer.capacity();
223 super.freeDirect(buffer);
224 ((UnpooledByteBufAllocator) alloc()).decrementDirect(capacity);
225 }
226 }
227
228 private static final class InstrumentedUnpooledDirectByteBuf extends UnpooledDirectByteBuf {
229 InstrumentedUnpooledDirectByteBuf(
230 UnpooledByteBufAllocator alloc, int initialCapacity, int maxCapacity) {
231 super(alloc, initialCapacity, maxCapacity);
232 }
233
234 @Override
235 protected ByteBuffer allocateDirect(int initialCapacity) {
236 ByteBuffer buffer = super.allocateDirect(initialCapacity);
237 ((UnpooledByteBufAllocator) alloc()).incrementDirect(buffer.capacity());
238 return buffer;
239 }
240
241 @Override
242 protected void freeDirect(ByteBuffer buffer) {
243 int capacity = buffer.capacity();
244 super.freeDirect(buffer);
245 ((UnpooledByteBufAllocator) alloc()).decrementDirect(capacity);
246 }
247 }
248
249 private static final class UnpooledByteBufAllocatorMetric implements ByteBufAllocatorMetric {
250 final LongCounter directCounter = PlatformDependent.newLongCounter();
251 final LongCounter heapCounter = PlatformDependent.newLongCounter();
252
253 @Override
254 public long usedHeapMemory() {
255 return heapCounter.value();
256 }
257
258 @Override
259 public long usedDirectMemory() {
260 return directCounter.value();
261 }
262
263 @Override
264 public String toString() {
265 return StringUtil.simpleClassName(this) +
266 "(usedHeapMemory: " + usedHeapMemory() + "; usedDirectMemory: " + usedDirectMemory() + ')';
267 }
268 }
269 }