(五) netty内存池:分配器PooledByteBufAllocator和内存池字节缓冲的表示

本文主要介绍了Netty中PooledByteBufAllocator的相关内容。包括其初始化时的三个主要属性,以及堆内存和直接内存的分配过程,每个线程有自己的分配缓冲,先从缓冲分配,不足时再从arena分配。还提到内存池字节缓冲由PooledHeapByteBuf和PooledDirectByteBuf表示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. PooledByteBufAllocator

1.1 PooledByteBufAllocator的初始化

分配器分配内存的API,在文章(三) netty非池化内存的分配与回收:UnpooledByteBufAllocator的前半部分有说明,可以参考。

PooledByteBufAllocator主要属性有三个:

    private final PoolArena<byte[]>[] heapArenas;
    private final PoolArena<ByteBuffer>[] directArenas;
	private final PoolThreadLocalCache threadCache;

heapArenas是堆内存的表示,每个arena内存以字节数组byte[]表示,注意arena不会直接持有内存,arena所有内存通过PoolChunk持有 。directArenas是直接内存的表示,每个arena的内存以DirectByteBuffer表示。threadCache是FastThreadLocal的子类对象。

这三个属性都在创建PooledByteBufAllocator对象时初始化:

==============构造器代码片段=============
// 初始化ThreadLocal
threadCache = new PoolThreadLocalCache(useCacheForAllThreads);

// 初始化heapArenas
heapArenas = newArenaArray(nHeapArena);
for (int i = 0; i < heapArenas.length; i ++) {
     PoolArena.HeapArena arena = new PoolArena.HeapArena(this,
             pageSize, maxOrder, pageShifts, chunkSize,
             directMemoryCacheAlignment);
     heapArenas[i] = arena;
 }

// 初始化directArenas
directArenas = newArenaArray(nDirectArena);
for (int i = 0; i < directArenas.length; i ++) {
    PoolArena.DirectArena arena = new PoolArena.DirectArena(
            this, pageSize, maxOrder, pageShifts, chunkSize, directMemoryCacheAlignment);
    directArenas[i] = arena;
}

1.2 PooledByteBufAllocator的内存分配

分配堆内存
当调用PooledByteBufAllocator.heapBuffer(int initialCapacity)分配内存时,之后会调用到newHeapBuffer(int initialCapacity, int maxCapacity)来分配,newHeapBuffer在PooledByteBufAllocator中的逻辑是:

  1. 从实例变量threadCache获取分配缓冲
    这里的要点是:netty每个线程都有自己的分配缓冲。线程第一次分配内存时,首先会给线程绑一个arena,用于后续内存的分配。arena获取的逻辑是最少持有线程数:arena会有个计数器,记录当前持有该arena的线程的个数,每次给线程分配arena时,分配持有线程数最少的arena。分配到arena后,会封装为PoolThreadCache对象,放到ThreadLocal中。后续每次分配内存,先从缓冲分配,缓冲分配不了,再从arena分配可用的内存。

  2. 调用arena.allocate方法进行内存的分配。

分配直接内存
整个过程,和分配堆内存一样,不在赘述。

2. 内存池字节缓冲的表示

内存池的场景,主要有PooledHeapByteBuf和PooledDirectByteBuf来表示分配到的字节缓冲。

它们都是PoolChunk分配到的一大段连续内存上的一小段,通过下标来控制访问范围。它们的主要属性在父类PooledByteBuf中:

    protected T memory;
    protected int offset;
    protected int length;

假设从同一个chunk上分配了两个堆字节缓冲,偏移量分别是(offset=16 bytes,length=16 bytes)和(offset=32 bytes,length=16 bytes),那么他们是一大段连续内存上的两个片段,如图所示:
netty pooled bytebuf

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值