1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package io.netty.buffer;
18
19 import static io.netty.util.internal.ObjectUtil.checkPositiveOrZero;
20
21 import io.netty.util.NettyRuntime;
22 import io.netty.util.concurrent.EventExecutor;
23 import io.netty.util.concurrent.FastThreadLocal;
24 import io.netty.util.concurrent.FastThreadLocalThread;
25 import io.netty.util.internal.PlatformDependent;
26 import io.netty.util.internal.StringUtil;
27 import io.netty.util.internal.SystemPropertyUtil;
28 import io.netty.util.internal.ThreadExecutorMap;
29 import io.netty.util.internal.logging.InternalLogger;
30 import io.netty.util.internal.logging.InternalLoggerFactory;
31
32 import java.nio.ByteBuffer;
33 import java.util.ArrayList;
34 import java.util.Collections;
35 import java.util.List;
36 import java.util.concurrent.TimeUnit;
37
38 public class PooledByteBufAllocator extends AbstractByteBufAllocator implements ByteBufAllocatorMetricProvider {
39
40 private static final InternalLogger logger = InternalLoggerFactory.getInstance(PooledByteBufAllocator.class);
41 private static final int DEFAULT_NUM_HEAP_ARENA;
42 private static final int DEFAULT_NUM_DIRECT_ARENA;
43
44 private static final int DEFAULT_PAGE_SIZE;
45 private static final int DEFAULT_MAX_ORDER;
46 private static final int DEFAULT_SMALL_CACHE_SIZE;
47 private static final int DEFAULT_NORMAL_CACHE_SIZE;
48 static final int DEFAULT_MAX_CACHED_BUFFER_CAPACITY;
49 private static final int DEFAULT_CACHE_TRIM_INTERVAL;
50 private static final long DEFAULT_CACHE_TRIM_INTERVAL_MILLIS;
51 private static final boolean DEFAULT_USE_CACHE_FOR_ALL_THREADS;
52 private static final int DEFAULT_DIRECT_MEMORY_CACHE_ALIGNMENT;
53 static final int DEFAULT_MAX_CACHED_BYTEBUFFERS_PER_CHUNK;
54 private static final boolean DEFAULT_DISABLE_CACHE_FINALIZERS_FOR_FAST_THREAD_LOCAL_THREADS;
55
56 private static final int MIN_PAGE_SIZE = 4096;
57 private static final int MAX_CHUNK_SIZE = (int) (((long) Integer.MAX_VALUE + 1) / 2);
58
59 private static final int CACHE_NOT_USED = 0;
60
61 private final Runnable trimTask = new Runnable() {
62 @Override
63 public void run() {
64 PooledByteBufAllocator.this.trimCurrentThreadCache();
65 }
66 };
67
68 static {
69 int defaultAlignment = SystemPropertyUtil.getInt(
70 "io.netty.allocator.directMemoryCacheAlignment", 0);
71 int defaultPageSize = SystemPropertyUtil.getInt("io.netty.allocator.pageSize", 8192);
72 Throwable pageSizeFallbackCause = null;
73 try {
74 validateAndCalculatePageShifts(defaultPageSize, defaultAlignment);
75 } catch (Throwable t) {
76 pageSizeFallbackCause = t;
77 defaultPageSize = 8192;
78 defaultAlignment = 0;
79 }
80 DEFAULT_PAGE_SIZE = defaultPageSize;
81 DEFAULT_DIRECT_MEMORY_CACHE_ALIGNMENT = defaultAlignment;
82
83 int defaultMaxOrder = SystemPropertyUtil.getInt("io.netty.allocator.maxOrder", 9);
84 Throwable maxOrderFallbackCause = null;
85 try {
86 validateAndCalculateChunkSize(DEFAULT_PAGE_SIZE, defaultMaxOrder);
87 } catch (Throwable t) {
88 maxOrderFallbackCause = t;
89 defaultMaxOrder = 9;
90 }
91 DEFAULT_MAX_ORDER = defaultMaxOrder;
92
93
94
95 final Runtime runtime = Runtime.getRuntime();
96
97
98
99
100
101
102
103
104 final int defaultMinNumArena = NettyRuntime.availableProcessors() * 2;
105 final int defaultChunkSize = DEFAULT_PAGE_SIZE << DEFAULT_MAX_ORDER;
106 DEFAULT_NUM_HEAP_ARENA = Math.max(0,
107 SystemPropertyUtil.getInt(
108 "io.netty.allocator.numHeapArenas",
109 (int) Math.min(
110 defaultMinNumArena,
111 runtime.maxMemory() / defaultChunkSize / 2 / 3)));
112 DEFAULT_NUM_DIRECT_ARENA = Math.max(0,
113 SystemPropertyUtil.getInt(
114 "io.netty.allocator.numDirectArenas",
115 (int) Math.min(
116 defaultMinNumArena,
117 PlatformDependent.maxDirectMemory() / defaultChunkSize / 2 / 3)));
118
119
120 DEFAULT_SMALL_CACHE_SIZE = SystemPropertyUtil.getInt("io.netty.allocator.smallCacheSize", 256);
121 DEFAULT_NORMAL_CACHE_SIZE = SystemPropertyUtil.getInt("io.netty.allocator.normalCacheSize", 64);
122
123
124
125 DEFAULT_MAX_CACHED_BUFFER_CAPACITY = SystemPropertyUtil.getInt(
126 "io.netty.allocator.maxCachedBufferCapacity", 32 * 1024);
127
128
129 DEFAULT_CACHE_TRIM_INTERVAL = SystemPropertyUtil.getInt(
130 "io.netty.allocator.cacheTrimInterval", 8192);
131
132 if (SystemPropertyUtil.contains("io.netty.allocation.cacheTrimIntervalMillis")) {
133 logger.warn("-Dio.netty.allocation.cacheTrimIntervalMillis is deprecated," +
134 " use -Dio.netty.allocator.cacheTrimIntervalMillis");
135
136 if (SystemPropertyUtil.contains("io.netty.allocator.cacheTrimIntervalMillis")) {
137
138 DEFAULT_CACHE_TRIM_INTERVAL_MILLIS = SystemPropertyUtil.getLong(
139 "io.netty.allocator.cacheTrimIntervalMillis", 0);
140 } else {
141 DEFAULT_CACHE_TRIM_INTERVAL_MILLIS = SystemPropertyUtil.getLong(
142 "io.netty.allocation.cacheTrimIntervalMillis", 0);
143 }
144 } else {
145 DEFAULT_CACHE_TRIM_INTERVAL_MILLIS = SystemPropertyUtil.getLong(
146 "io.netty.allocator.cacheTrimIntervalMillis", 0);
147 }
148
149 DEFAULT_USE_CACHE_FOR_ALL_THREADS = SystemPropertyUtil.getBoolean(
150 "io.netty.allocator.useCacheForAllThreads", false);
151
152 DEFAULT_DISABLE_CACHE_FINALIZERS_FOR_FAST_THREAD_LOCAL_THREADS = SystemPropertyUtil.getBoolean(
153 "io.netty.allocator.disableCacheFinalizersForFastThreadLocalThreads", false);
154
155
156
157 DEFAULT_MAX_CACHED_BYTEBUFFERS_PER_CHUNK = SystemPropertyUtil.getInt(
158 "io.netty.allocator.maxCachedByteBuffersPerChunk", 1023);
159
160 if (logger.isDebugEnabled()) {
161 logger.debug("-Dio.netty.allocator.numHeapArenas: {}", DEFAULT_NUM_HEAP_ARENA);
162 logger.debug("-Dio.netty.allocator.numDirectArenas: {}", DEFAULT_NUM_DIRECT_ARENA);
163 if (pageSizeFallbackCause == null) {
164 logger.debug("-Dio.netty.allocator.pageSize: {}", DEFAULT_PAGE_SIZE);
165 } else {
166 logger.debug("-Dio.netty.allocator.pageSize: {}", DEFAULT_PAGE_SIZE, pageSizeFallbackCause);
167 }
168 if (maxOrderFallbackCause == null) {
169 logger.debug("-Dio.netty.allocator.maxOrder: {}", DEFAULT_MAX_ORDER);
170 } else {
171 logger.debug("-Dio.netty.allocator.maxOrder: {}", DEFAULT_MAX_ORDER, maxOrderFallbackCause);
172 }
173 logger.debug("-Dio.netty.allocator.chunkSize: {}", DEFAULT_PAGE_SIZE << DEFAULT_MAX_ORDER);
174 logger.debug("-Dio.netty.allocator.smallCacheSize: {}", DEFAULT_SMALL_CACHE_SIZE);
175 logger.debug("-Dio.netty.allocator.normalCacheSize: {}", DEFAULT_NORMAL_CACHE_SIZE);
176 logger.debug("-Dio.netty.allocator.maxCachedBufferCapacity: {}", DEFAULT_MAX_CACHED_BUFFER_CAPACITY);
177 logger.debug("-Dio.netty.allocator.cacheTrimInterval: {}", DEFAULT_CACHE_TRIM_INTERVAL);
178 logger.debug("-Dio.netty.allocator.cacheTrimIntervalMillis: {}", DEFAULT_CACHE_TRIM_INTERVAL_MILLIS);
179 logger.debug("-Dio.netty.allocator.useCacheForAllThreads: {}", DEFAULT_USE_CACHE_FOR_ALL_THREADS);
180 logger.debug("-Dio.netty.allocator.maxCachedByteBuffersPerChunk: {}",
181 DEFAULT_MAX_CACHED_BYTEBUFFERS_PER_CHUNK);
182 logger.debug("-Dio.netty.allocator.disableCacheFinalizersForFastThreadLocalThreads: {}",
183 DEFAULT_DISABLE_CACHE_FINALIZERS_FOR_FAST_THREAD_LOCAL_THREADS);
184 }
185 }
186
187 public static final PooledByteBufAllocator DEFAULT =
188 new PooledByteBufAllocator(!PlatformDependent.isExplicitNoPreferDirect());
189
190 private final PoolArena<byte[]>[] heapArenas;
191 private final PoolArena<ByteBuffer>[] directArenas;
192 private final int smallCacheSize;
193 private final int normalCacheSize;
194 private final List<PoolArenaMetric> heapArenaMetrics;
195 private final List<PoolArenaMetric> directArenaMetrics;
196 private final PoolThreadLocalCache threadCache;
197 private final int chunkSize;
198 private final PooledByteBufAllocatorMetric metric;
199
200 public PooledByteBufAllocator() {
201 this(false);
202 }
203
204 @SuppressWarnings("deprecation")
205 public PooledByteBufAllocator(boolean preferDirect) {
206 this(preferDirect, DEFAULT_NUM_HEAP_ARENA, DEFAULT_NUM_DIRECT_ARENA, DEFAULT_PAGE_SIZE, DEFAULT_MAX_ORDER);
207 }
208
209 @SuppressWarnings("deprecation")
210 public PooledByteBufAllocator(int nHeapArena, int nDirectArena, int pageSize, int maxOrder) {
211 this(false, nHeapArena, nDirectArena, pageSize, maxOrder);
212 }
213
214
215
216
217
218 @Deprecated
219 public PooledByteBufAllocator(boolean preferDirect, int nHeapArena, int nDirectArena, int pageSize, int maxOrder) {
220 this(preferDirect, nHeapArena, nDirectArena, pageSize, maxOrder,
221 0, DEFAULT_SMALL_CACHE_SIZE, DEFAULT_NORMAL_CACHE_SIZE);
222 }
223
224
225
226
227
228 @Deprecated
229 public PooledByteBufAllocator(boolean preferDirect, int nHeapArena, int nDirectArena, int pageSize, int maxOrder,
230 int tinyCacheSize, int smallCacheSize, int normalCacheSize) {
231 this(preferDirect, nHeapArena, nDirectArena, pageSize, maxOrder, smallCacheSize,
232 normalCacheSize, DEFAULT_USE_CACHE_FOR_ALL_THREADS, DEFAULT_DIRECT_MEMORY_CACHE_ALIGNMENT);
233 }
234
235
236
237
238
239 @Deprecated
240 public PooledByteBufAllocator(boolean preferDirect, int nHeapArena,
241 int nDirectArena, int pageSize, int maxOrder, int tinyCacheSize,
242 int smallCacheSize, int normalCacheSize,
243 boolean useCacheForAllThreads) {
244 this(preferDirect, nHeapArena, nDirectArena, pageSize, maxOrder,
245 smallCacheSize, normalCacheSize,
246 useCacheForAllThreads);
247 }
248
249 public PooledByteBufAllocator(boolean preferDirect, int nHeapArena,
250 int nDirectArena, int pageSize, int maxOrder,
251 int smallCacheSize, int normalCacheSize,
252 boolean useCacheForAllThreads) {
253 this(preferDirect, nHeapArena, nDirectArena, pageSize, maxOrder,
254 smallCacheSize, normalCacheSize,
255 useCacheForAllThreads, DEFAULT_DIRECT_MEMORY_CACHE_ALIGNMENT);
256 }
257
258
259
260
261
262 @Deprecated
263 public PooledByteBufAllocator(boolean preferDirect, int nHeapArena, int nDirectArena, int pageSize, int maxOrder,
264 int tinyCacheSize, int smallCacheSize, int normalCacheSize,
265 boolean useCacheForAllThreads, int directMemoryCacheAlignment) {
266 this(preferDirect, nHeapArena, nDirectArena, pageSize, maxOrder,
267 smallCacheSize, normalCacheSize,
268 useCacheForAllThreads, directMemoryCacheAlignment);
269 }
270
271 public PooledByteBufAllocator(boolean preferDirect, int nHeapArena, int nDirectArena, int pageSize, int maxOrder,
272 int smallCacheSize, int normalCacheSize,
273 boolean useCacheForAllThreads, int directMemoryCacheAlignment) {
274 super(preferDirect);
275 if (PlatformDependent.isJfrEnabled()) {
276 JfrEventRegistration.init();
277 }
278 threadCache = new PoolThreadLocalCache(useCacheForAllThreads);
279 this.smallCacheSize = smallCacheSize;
280 this.normalCacheSize = normalCacheSize;
281
282 if (directMemoryCacheAlignment != 0) {
283 if (!PlatformDependent.hasAlignDirectByteBuffer()) {
284 throw new UnsupportedOperationException("Buffer alignment is not supported. " +
285 "Either Unsafe or ByteBuffer.alignSlice() must be available.");
286 }
287
288
289 pageSize = (int) PlatformDependent.align(pageSize, directMemoryCacheAlignment);
290 }
291
292 chunkSize = validateAndCalculateChunkSize(pageSize, maxOrder);
293
294 checkPositiveOrZero(nHeapArena, "nHeapArena");
295 checkPositiveOrZero(nDirectArena, "nDirectArena");
296
297 checkPositiveOrZero(directMemoryCacheAlignment, "directMemoryCacheAlignment");
298 if (directMemoryCacheAlignment > 0 && !isDirectMemoryCacheAlignmentSupported()) {
299 throw new IllegalArgumentException("directMemoryCacheAlignment is not supported");
300 }
301
302 if ((directMemoryCacheAlignment & -directMemoryCacheAlignment) != directMemoryCacheAlignment) {
303 throw new IllegalArgumentException("directMemoryCacheAlignment: "
304 + directMemoryCacheAlignment + " (expected: power of two)");
305 }
306
307 int pageShifts = validateAndCalculatePageShifts(pageSize, directMemoryCacheAlignment);
308
309 if (nHeapArena > 0) {
310 heapArenas = newArenaArray(nHeapArena);
311 List<PoolArenaMetric> metrics = new ArrayList<PoolArenaMetric>(heapArenas.length);
312 final SizeClasses sizeClasses = new SizeClasses(pageSize, pageShifts, chunkSize, 0);
313 for (int i = 0; i < heapArenas.length; i ++) {
314 PoolArena.HeapArena arena = new PoolArena.HeapArena(this, sizeClasses);
315 heapArenas[i] = arena;
316 metrics.add(arena);
317 }
318 heapArenaMetrics = Collections.unmodifiableList(metrics);
319 } else {
320 heapArenas = null;
321 heapArenaMetrics = Collections.emptyList();
322 }
323
324 if (nDirectArena > 0) {
325 directArenas = newArenaArray(nDirectArena);
326 List<PoolArenaMetric> metrics = new ArrayList<PoolArenaMetric>(directArenas.length);
327 final SizeClasses sizeClasses = new SizeClasses(pageSize, pageShifts, chunkSize,
328 directMemoryCacheAlignment);
329 for (int i = 0; i < directArenas.length; i ++) {
330 PoolArena.DirectArena arena = new PoolArena.DirectArena(this, sizeClasses);
331 directArenas[i] = arena;
332 metrics.add(arena);
333 }
334 directArenaMetrics = Collections.unmodifiableList(metrics);
335 } else {
336 directArenas = null;
337 directArenaMetrics = Collections.emptyList();
338 }
339 metric = new PooledByteBufAllocatorMetric(this);
340 }
341
342 @SuppressWarnings("unchecked")
343 private static <T> PoolArena<T>[] newArenaArray(int size) {
344 return new PoolArena[size];
345 }
346
347 private static int validateAndCalculatePageShifts(int pageSize, int alignment) {
348 if (pageSize < MIN_PAGE_SIZE) {
349 throw new IllegalArgumentException("pageSize: " + pageSize + " (expected: " + MIN_PAGE_SIZE + ')');
350 }
351
352 if ((pageSize & pageSize - 1) != 0) {
353 throw new IllegalArgumentException("pageSize: " + pageSize + " (expected: power of 2)");
354 }
355
356 if (pageSize < alignment) {
357 throw new IllegalArgumentException("Alignment cannot be greater than page size. " +
358 "Alignment: " + alignment + ", page size: " + pageSize + '.');
359 }
360
361
362 return Integer.SIZE - 1 - Integer.numberOfLeadingZeros(pageSize);
363 }
364
365 private static int validateAndCalculateChunkSize(int pageSize, int maxOrder) {
366 if (maxOrder < 0 || maxOrder > 14) {
367 throw new IllegalArgumentException("maxOrder: " + maxOrder + " (expected: 0-14)");
368 }
369
370
371 int chunkSize = pageSize;
372 for (int i = maxOrder; i > 0; i --) {
373 if (chunkSize > MAX_CHUNK_SIZE / 2) {
374 throw new IllegalArgumentException(String.format(
375 "pageSize (%d) << maxOrder (%d) must not exceed %d", pageSize, maxOrder, MAX_CHUNK_SIZE));
376 }
377 chunkSize <<= 1;
378 }
379 return chunkSize;
380 }
381
382 @Override
383 protected ByteBuf newHeapBuffer(int initialCapacity, int maxCapacity) {
384 PoolThreadCache cache = threadCache.get();
385 PoolArena<byte[]> heapArena = cache.heapArena;
386
387 final AbstractByteBuf buf;
388 if (heapArena != null) {
389 buf = heapArena.allocate(cache, initialCapacity, maxCapacity);
390 } else {
391 buf = PlatformDependent.hasUnsafe() ?
392 new UnpooledUnsafeHeapByteBuf(this, initialCapacity, maxCapacity) :
393 new UnpooledHeapByteBuf(this, initialCapacity, maxCapacity);
394 onAllocateBuffer(buf, false, false);
395 }
396 return toLeakAwareBuffer(buf);
397 }
398
399 @Override
400 protected ByteBuf newDirectBuffer(int initialCapacity, int maxCapacity) {
401 PoolThreadCache cache = threadCache.get();
402 PoolArena<ByteBuffer> directArena = cache.directArena;
403
404 final AbstractByteBuf buf;
405 if (directArena != null) {
406 buf = directArena.allocate(cache, initialCapacity, maxCapacity);
407 } else {
408 buf = UnsafeByteBufUtil.newDirectByteBuf(this, initialCapacity, maxCapacity);
409 onAllocateBuffer(buf, false, false);
410 }
411 return toLeakAwareBuffer(buf);
412 }
413
414
415
416
417 public static int defaultNumHeapArena() {
418 return DEFAULT_NUM_HEAP_ARENA;
419 }
420
421
422
423
424 public static int defaultNumDirectArena() {
425 return DEFAULT_NUM_DIRECT_ARENA;
426 }
427
428
429
430
431 public static int defaultPageSize() {
432 return DEFAULT_PAGE_SIZE;
433 }
434
435
436
437
438 public static int defaultMaxOrder() {
439 return DEFAULT_MAX_ORDER;
440 }
441
442
443
444
445
446 public static boolean defaultDisableCacheFinalizersForFastThreadLocalThreads() {
447 return DEFAULT_DISABLE_CACHE_FINALIZERS_FOR_FAST_THREAD_LOCAL_THREADS;
448 }
449
450
451
452
453 public static boolean defaultUseCacheForAllThreads() {
454 return DEFAULT_USE_CACHE_FOR_ALL_THREADS;
455 }
456
457
458
459
460 public static boolean defaultPreferDirect() {
461 return PlatformDependent.directBufferPreferred();
462 }
463
464
465
466
467
468
469 @Deprecated
470 public static int defaultTinyCacheSize() {
471 return 0;
472 }
473
474
475
476
477 public static int defaultSmallCacheSize() {
478 return DEFAULT_SMALL_CACHE_SIZE;
479 }
480
481
482
483
484 public static int defaultNormalCacheSize() {
485 return DEFAULT_NORMAL_CACHE_SIZE;
486 }
487
488
489
490
491 public static boolean isDirectMemoryCacheAlignmentSupported() {
492 return PlatformDependent.hasUnsafe();
493 }
494
495 @Override
496 public boolean isDirectBufferPooled() {
497 return directArenas != null;
498 }
499
500
501
502
503
504
505 @Deprecated
506 public boolean hasThreadLocalCache() {
507 return threadCache.isSet();
508 }
509
510
511
512
513
514 @Deprecated
515 public void freeThreadLocalCache() {
516 threadCache.remove();
517 }
518
519 private final class PoolThreadLocalCache extends FastThreadLocal<PoolThreadCache> {
520 private final boolean useCacheForAllThreads;
521
522 PoolThreadLocalCache(boolean useCacheForAllThreads) {
523 this.useCacheForAllThreads = useCacheForAllThreads;
524 }
525
526 @Override
527 protected synchronized PoolThreadCache initialValue() {
528 final PoolArena<byte[]> heapArena = leastUsedArena(heapArenas);
529 final PoolArena<ByteBuffer> directArena = leastUsedArena(directArenas);
530
531 final Thread current = Thread.currentThread();
532 final EventExecutor executor = ThreadExecutorMap.currentExecutor();
533
534 if (useCacheForAllThreads ||
535
536 FastThreadLocalThread.currentThreadHasFastThreadLocal() ||
537
538
539 executor != null) {
540 final PoolThreadCache cache = new PoolThreadCache(
541 heapArena, directArena, smallCacheSize, normalCacheSize,
542 DEFAULT_MAX_CACHED_BUFFER_CAPACITY, DEFAULT_CACHE_TRIM_INTERVAL, useCacheFinalizers());
543
544 if (DEFAULT_CACHE_TRIM_INTERVAL_MILLIS > 0) {
545 if (executor != null) {
546 executor.scheduleAtFixedRate(trimTask, DEFAULT_CACHE_TRIM_INTERVAL_MILLIS,
547 DEFAULT_CACHE_TRIM_INTERVAL_MILLIS, TimeUnit.MILLISECONDS);
548 }
549 }
550 return cache;
551 }
552
553 return new PoolThreadCache(heapArena, directArena, 0, 0, 0, 0, false);
554 }
555
556 @Override
557 protected void onRemoval(PoolThreadCache threadCache) {
558 threadCache.free(false);
559 }
560
561 private <T> PoolArena<T> leastUsedArena(PoolArena<T>[] arenas) {
562 if (arenas == null || arenas.length == 0) {
563 return null;
564 }
565
566 PoolArena<T> minArena = arenas[0];
567
568
569 if (minArena.numThreadCaches.get() == CACHE_NOT_USED) {
570 return minArena;
571 }
572 for (int i = 1; i < arenas.length; i++) {
573 PoolArena<T> arena = arenas[i];
574 if (arena.numThreadCaches.get() < minArena.numThreadCaches.get()) {
575 minArena = arena;
576 }
577 }
578
579 return minArena;
580 }
581 }
582
583 private static boolean useCacheFinalizers() {
584 if (!defaultDisableCacheFinalizersForFastThreadLocalThreads()) {
585 return true;
586 }
587 return FastThreadLocalThread.currentThreadWillCleanupFastThreadLocals();
588 }
589
590 @Override
591 public PooledByteBufAllocatorMetric metric() {
592 return metric;
593 }
594
595
596
597
598
599
600 @Deprecated
601 public int numHeapArenas() {
602 return heapArenaMetrics.size();
603 }
604
605
606
607
608
609
610 @Deprecated
611 public int numDirectArenas() {
612 return directArenaMetrics.size();
613 }
614
615
616
617
618
619
620 @Deprecated
621 public List<PoolArenaMetric> heapArenas() {
622 return heapArenaMetrics;
623 }
624
625
626
627
628
629
630 @Deprecated
631 public List<PoolArenaMetric> directArenas() {
632 return directArenaMetrics;
633 }
634
635
636
637
638
639
640 @Deprecated
641 public int numThreadLocalCaches() {
642 return Math.max(numThreadLocalCaches(heapArenas), numThreadLocalCaches(directArenas));
643 }
644
645 private static int numThreadLocalCaches(PoolArena<?>[] arenas) {
646 if (arenas == null) {
647 return 0;
648 }
649
650 int total = 0;
651 for (PoolArena<?> arena : arenas) {
652 total += arena.numThreadCaches.get();
653 }
654
655 return total;
656 }
657
658
659
660
661
662
663 @Deprecated
664 public int tinyCacheSize() {
665 return 0;
666 }
667
668
669
670
671
672
673 @Deprecated
674 public int smallCacheSize() {
675 return smallCacheSize;
676 }
677
678
679
680
681
682
683 @Deprecated
684 public int normalCacheSize() {
685 return normalCacheSize;
686 }
687
688
689
690
691
692
693 @Deprecated
694 public final int chunkSize() {
695 return chunkSize;
696 }
697
698 final long usedHeapMemory() {
699 return usedMemory(heapArenas);
700 }
701
702 final long usedDirectMemory() {
703 return usedMemory(directArenas);
704 }
705
706 private static long usedMemory(PoolArena<?>[] arenas) {
707 if (arenas == null) {
708 return -1;
709 }
710 long used = 0;
711 for (PoolArena<?> arena : arenas) {
712 used += arena.numActiveBytes();
713 if (used < 0) {
714 return Long.MAX_VALUE;
715 }
716 }
717 return used;
718 }
719
720
721
722
723
724
725
726 public final long pinnedHeapMemory() {
727 return pinnedMemory(heapArenas);
728 }
729
730
731
732
733
734
735
736 public final long pinnedDirectMemory() {
737 return pinnedMemory(directArenas);
738 }
739
740 private static long pinnedMemory(PoolArena<?>[] arenas) {
741 if (arenas == null) {
742 return -1;
743 }
744 long used = 0;
745 for (PoolArena<?> arena : arenas) {
746 used += arena.numPinnedBytes();
747 if (used < 0) {
748 return Long.MAX_VALUE;
749 }
750 }
751 return used;
752 }
753
754 final PoolThreadCache threadCache() {
755 PoolThreadCache cache = threadCache.get();
756 assert cache != null;
757 return cache;
758 }
759
760
761
762
763
764
765
766 public boolean trimCurrentThreadCache() {
767 PoolThreadCache cache = threadCache.getIfExists();
768 if (cache != null) {
769 cache.trim();
770 return true;
771 }
772 return false;
773 }
774
775
776
777
778
779 public String dumpStats() {
780 int heapArenasLen = heapArenas == null ? 0 : heapArenas.length;
781 StringBuilder buf = new StringBuilder(512)
782 .append(heapArenasLen)
783 .append(" heap arena(s):")
784 .append(StringUtil.NEWLINE);
785 if (heapArenasLen > 0) {
786 for (PoolArena<byte[]> a: heapArenas) {
787 buf.append(a);
788 }
789 }
790
791 int directArenasLen = directArenas == null ? 0 : directArenas.length;
792
793 buf.append(directArenasLen)
794 .append(" direct arena(s):")
795 .append(StringUtil.NEWLINE);
796 if (directArenasLen > 0) {
797 for (PoolArena<ByteBuffer> a: directArenas) {
798 buf.append(a);
799 }
800 }
801
802 return buf.toString();
803 }
804
805 static void onAllocateBuffer(AbstractByteBuf buf, boolean pooled, boolean threadLocal) {
806 if (PlatformDependent.isJfrEnabled() && AllocateBufferEvent.isEventEnabled()) {
807 AllocateBufferEvent event = new AllocateBufferEvent();
808 if (event.shouldCommit()) {
809 event.fill(buf, PooledByteBufAllocator.class);
810 event.chunkPooled = pooled;
811 event.chunkThreadLocal = threadLocal;
812 event.commit();
813 }
814 }
815 }
816
817 static void onDeallocateBuffer(AbstractByteBuf buf) {
818 if (PlatformDependent.isJfrEnabled() && FreeBufferEvent.isEventEnabled()) {
819 FreeBufferEvent event = new FreeBufferEvent();
820 if (event.shouldCommit()) {
821 event.fill(buf, PooledByteBufAllocator.class);
822 event.commit();
823 }
824 }
825 }
826
827 static void onReallocateBuffer(AbstractByteBuf buf, int newCapacity) {
828 if (PlatformDependent.isJfrEnabled() && ReallocateBufferEvent.isEventEnabled()) {
829 ReallocateBufferEvent event = new ReallocateBufferEvent();
830 if (event.shouldCommit()) {
831 event.fill(buf, PooledByteBufAllocator.class);
832 event.newCapacity = newCapacity;
833 event.commit();
834 }
835 }
836 }
837
838 static void onAllocateChunk(ChunkInfo chunk, boolean pooled) {
839 if (PlatformDependent.isJfrEnabled() && AllocateChunkEvent.isEventEnabled()) {
840 AllocateChunkEvent event = new AllocateChunkEvent();
841 if (event.shouldCommit()) {
842 event.fill(chunk, PooledByteBufAllocator.class);
843 event.pooled = pooled;
844 event.threadLocal = false;
845 event.commit();
846 }
847 }
848 }
849
850 static void onDeallocateChunk(ChunkInfo chunk, boolean pooled) {
851 if (PlatformDependent.isJfrEnabled() && FreeChunkEvent.isEventEnabled()) {
852 FreeChunkEvent event = new FreeChunkEvent();
853 if (event.shouldCommit()) {
854 event.fill(chunk, PooledByteBufAllocator.class);
855 event.pooled = pooled;
856 event.commit();
857 }
858 }
859 }
860 }