netty5学习笔记-内存池1-PoolChunk

        从netty 4开始,netty加入了内存池管理,采用内存池管理比普通的new ByteBuf性能提高了数(2)十倍。相信有些朋友会和我一样,对他的实现方式很感兴趣。这里把学习netty内存池的过程记录下来,与大家一起分享。

        首先给大家介绍的是PoolChunk, 该类主要负责内存块的分配与回收,首先来看看两个重要的术语:

page: 可以分配的最小的内存块单位。

chunk: 一堆page的集合。

        下面我们用一张图直观的看下PoolChunk是如何管理内存的:

        上图中是一个默认大小的chunk, 由2048个page组成了一个chunk,一个page的大小为8192, chunk之上有11层节点,最后一层节点数与page数量相等。每次内存分配需要保证内存的连续性,这样才能简单的操作分配到的内存,因此这里构造了一颗完整的平衡二叉树,所有子节点的管理的内存也属于其父节点。如果我们想获取一个8K的内存,则只需在第11层找一个可用节点即可,而如果我们需要16K的数据,则需要在第10层找一个可用节点。如果一个节点存在一个已经被分配的子节点,则该节点不能被分配,例如我们需要16K内存,这个时候id为2048的节点已经被分配,id为2049的节点未分配,就不能直接分配1024这个节点,因为这个节点下的内存只有8K了。

        通过上面这个树结构,我们可以看到每次内存分配都是8K*(2^n), 比如需要24K内存时,实际上会申请到一块32K的内存。为了分配一个大小为chunkSize/(2^k)的内存段,需要在深度为k的层从左开始查找可用节点。如想分配16K的内存,chunkSize = 16M, 则k=10, 需要从第10层找一个空闲的节点分配内存。

        如何高效的从这么多page中分配到指定的内存呢。来看看下面这个图:

      

        这个图与上图结构一致,不同的是上方的二叉树的值为当前的层数,两张图和起来用一个数组memoryMap表示,上面的图中的数字表示数组的index,下面的图中的数字表示当前节点及其子节点可以分配的层的高度。如对于id=512的节点,其深度为9,则:

1)memoryMap[512] = 9,则表示其本身到下面所有的子节点都可以被分配;

2)memoryMap[512] = val (从10到11), 则表示512节点下有子节点已经分配过,则该节点不能直接被分配,而其子节点中的第val和val以下层还存在未分配的节点;

3)memoryMap[512] = 12 (即总层数 + 1), 可分配的深度已经大于总层数,  则该节点下的所有子节点都已经被分配。

        下面我们在从源码分析下PoolChunk是如何实现的,首先看看它的构造方法:

PoolChunk(PoolArena<T> arena, T memory, int pageSize, int maxOrder, int pageShifts, int chunkSize) {
        unpooled = false;
        this.arena = arena; 
        // memory是一个容量为chunkSize的byte[](heap方式)或ByteBuffer(direct方式)
        this.memory = memory;
        // 每个page的大小,默认为8192
        this.pageSize = pageSize;
        // 13,   2 ^ 13 = 8192
        this.pageShifts = pageShifts;
        // 默认11
        this.maxOrder = maxOrder;
        // 默认 8192 << 11 = 16MB
        this.chunkSize = chunkSize;
        // 12, 当memoryMap[id] = unusable时,则表示id节点已被分配
        unusable = (byte) (maxOrder + 1);
        // 24, 2 ^ 24 = 16M
        log2ChunkSize = log2(chunkSize);
        // -8192
        subpageOverflowMask = ~(pageSize - 1);
        freeBytes = chunkSize;

        assert maxOrder < 30 : "maxOrder should be < 30, but is: " + maxOrder;
        // 2048, 最多能被分配的Subpage个数
        maxSubpageAllocs = 1 &l
  • 7
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值