日常推荐:
Netty PoolArea原理探究
我们继续带着问题去看这部分。
PoolArea在netty中是如何使用的
1.PooledByteBufAllocator
在PooledByteBufAllocator类中有对应的PoolArena数组,此数组时与线程数相关的,目的是为了减少在多线程分配内存时线程竞争。
public static final PooledByteBufAllocator DEFAULT =
new PooledByteBufAllocator(PlatformDependent.directBufferPreferred());
private final PoolArena<byte[]>[] heapArenas;
private final PoolArena<ByteBuffer>[] directArenas;
public PooledByteBufAllocator(....){
if (nHeapArena > 0) {
heapArenas = newArenaArray(nHeapArena);
List<PoolArenaMetric> metrics = new ArrayList<PoolArenaMetric>(heapArenas.length);
for (int i = 0; i < heapArenas.length; i ++) {
PoolArena.HeapArena arena = new PoolArena.HeapArena(this,
pageSize, maxOrder, pageShifts, chunkSize,
directMemoryCacheAlignment);
heapArenas[i] = arena;
metrics.add(arena);
}
heapArenaMetrics = Collections.unmodifiableList(metrics);
}
}
PooledByteBufAllocator类中有一个默认的PooledByteBufAllocator实例属性,这个数据一般会使用在ServerBootstrap作为workGroup默认的ByteBufAllocator。通过PooledByteBufAllocator的构造函数,也可知DEFAULT中PoolArena相关信息是已经初始化完毕的。
2.newXXXByteBuf时
当分配池化内存PooledDirectByteBuf/PooledHeapByteBuf时:以PooledDirectByteBuf为例
protected ByteBuf newDirectBuffer(int initialCapacity, int maxCapacity) {
PoolThreadCache cache = threadCache.get();
PoolArena<ByteBuffer> directArena = cache.directArena;
final ByteBuf buf;
if (directArena != null) {
buf = directArena.allocate(cache, initialCapacity, maxCapacity);
} else {
buf = PlatformDependent.hasUnsafe() ?
UnsafeByteBufUtil.newUnsafeDirectByteBuf(this, initialCapacity, maxCapacity) :
new UnpooledDirectByteBuf(this, initialCapacity, maxCapacity);
}
return toLeakAwareBuffer(buf);
}
通过我们之前文章:Netty中自研的FastThreadLocal、FastThreadLocalThread的使用
分析过threadCache,PoolThreadLocalCache中的initialValue()方法会初始化PoolThreadCache,PoolThreadCache中会注入PooledByteBufAllocator中已经初始化好的Pool Area:
@Override
protected synchronized PoolThreadCache initialValue() {
final PoolArena<byte[]> heapArena = leastUsedArena(heapArenas);
final PoolArena<ByteBuffer> directArena = leastUsedArena(directArenas);
final Thread current = Thread.currentThread();
if (useCacheForAllThreads || current instanceof FastThreadLocalThread) {
final PoolThreadCache cache = new PoolThreadCache(
heapArena, directArena, tinyCacheSize, smallCacheSize, normalCacheSize,
DEFAULT_MAX_CACHED_BUFFER_CAPACITY, DEFAULT_CACHE_TRIM_INTERVAL);
if (DEFAULT_CACHE_TRIM_INTERVAL_MILLIS > 0) {
final EventExecutor executor = ThreadExecutorMap.currentExecutor();
if (executor != null) {
executor.scheduleAtFixedRate(trimTask, DEFAULT_CACHE_TRIM_INTERVAL_MILLIS,
DEFAULT_CACHE_TRIM_INTERVAL_MILLIS, TimeUnit.MILLISECONDS);
}
}
return cache;
}
// No caching so just use 0 as sizes.
return new PoolThreadCache(heapArena, directArena, 0, 0, 0, 0, 0);
}
最后PoolThreadCache会记录到对应的XXXByteBuf中。