netty内存分配 (Buddy算法)

本文只简述Buddy算法在netty内存池中简单实现
  1. 内存分配的最小单位为16B。
  2. < 512B的请求为Tiny,< 8KB(PageSize)的请求为Small,<= 16MB(ChunkSize)的请求为Normal,> 16MB(ChunkSize)的请求为Huge。
  3. < 512B的请求以16B为起点每次增加16B;>= 512B的请求则每次加倍。
  4. 不在表格中的请求大小,将向上规范化到表格中的数据,比如:请求分配511B、512B、513B,将依次规范化为512B、512B、1KB。
Chunk 和Page

buddy算法.png

1个Chunk由2048个Page组成,每个Page大小8K,图中最底层表示一个被切分为2048个Page的Chunk块。自底向上,每一层节点作为上一层的子节点构造出一棵满二叉树,然后按层分配满足要求的内存块。以待分配序列8KB、16KB、8KB为例分析分配过程(每个Page大小8KB)

  1. 8KB–需要一个Page,第11层满足要求,故分配2048节点即Page0;
  2. 16KB–需要两个Page,故需要在第10层进行分配,而1024的子节点2048已分配,从左到右找到满足要求的1025节点,故分配节点1025即Page2和Page3;
  3. 8KB–需要一个Page,第11层满足要求,2048已分配,从左到右找到2049节点即Page1进行分配。

分配结束后,已分配连续的Page0-Page3,这样的连续内存块,大大减少内部碎片并提高内存使用率。

netty的PoolChunk维护着一个memoryMap(是一个数组)

        int maxOrder = 11;
        int maxSubpageAllocs = 1 << maxOrder;

        // Generate the memory map.
        byte[] memoryMap = new byte[maxSubpageAllocs << 1];
        byte[] depthMap = new byte[memoryMap.length];
        int memoryMapIndex = 1;
        for (int d = 0; d <= maxOrder; ++ d) { // move down the tree one level at a time
            int depth = 1 << d;
            for (int p = 0; p < depth; ++ p) {
                // in each level traverse left to right and set value to the depth of subtree
                memoryMap[memoryMapIndex] = (byte) d;
                depthMap[memoryMapIndex] = (byte) d;
                memoryMapIndex ++;
            }
        }

memoryMap数组中每个位置保存的是该节点所在的层数,有什么作用?对于节点512,其层数是9,则:

  1. 如果memoryMap[512] = 9,则表示其本身到下面所有的子节点都可以被分配;
  2. 如果memoryMap[512] = 10, 则表示节点512下有子节点已经分配过,则该节点不能直接被分配,而其子节点中的第10层还存在未分配的节点;
  3. 如果memoryMap[512] = 12 (即总层数 + 1), 可分配的深度已经大于总层数, 则表示该节点下的所有子节点都已经被分配。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值