美文网首页
Netty源码分析----PoolChunkList

Netty源码分析----PoolChunkList

作者: _六道木 | 来源:发表于2018-04-14 16:01 被阅读18次

    (*文章基于Netty4.1.22版本)

    整体介绍

    在Netty的内存分配的整体架构中,按我的理解,PoolChunkList是为了解决随着分配的次数增加,分配一段连续内存失败率提高的问题。
    试想一下在Chunk中我们分配了很多小的内存,16B,32B,把整个Chunk都切割成这种小的内存块,那么当我们想要分配8KB或者更大的内存的时候,就会失败,因为其他Chunk被切割成很小的内存碎片,无法分配很大的一段内存,所以PoolChunkList的结构就出现了,将不同使用率的PoolChunk分隔开,增加了分配大的连续段成功的几率。
    PoolChunkList是一个链表,结构如下:


    PoolChunkList结构.png

    在整个PoolArena中,共有6个PoolChunkList,使用率越大的在链表的后面,按照不同的使用率,命名如下:

    1. qInit:使用率 0 ~ 25
    2. q000:使用率 1 ~ 50
    3. q025:使用率 25 ~ 75
    4. q050:使用率 50 ~ 100
    5. q075:使用率 75 ~ 100
    6. q100:使用率 100 ~ 100

    源码分析

    变量介绍

        private final PoolArena<T> arena;//该 Chunk所属的Arena
        private final PoolChunkList<T> nextList;// 下一个使用率的ChunkList
        private final int minUsage;// 最小使用率
        private final int maxUsage;// 最小使用率
        private final int maxCapacity;// 最大的容量
        private PoolChunk<T> head;// ChunkList中的头节点
    

    初始化

        PoolChunkList(PoolArena<T> arena, PoolChunkList<T> nextList, int minUsage, int maxUsage, int chunkSize) {
            assert minUsage <= maxUsage;
            this.arena = arena;
            this.nextList = nextList;
            this.minUsage = minUsage;
            this.maxUsage = maxUsage;
            maxCapacity = calculateMaxCapacity(minUsage, chunkSize);
        }
    

    简单的赋值操作,重点看下calculateMaxCapacity方法

        private static int calculateMaxCapacity(int minUsage, int chunkSize) {
            minUsage = minUsage0(minUsage);//max(1, minUsage)
    
            if (minUsage == 100) {// 如果最小使用率都百分百了,自然最大可用空间为0
                return 0;
            }
            return  (int) (chunkSize * (100L - minUsage) / 100L);
        }
    

    分配

        boolean allocate(PooledByteBuf<T> buf, int reqCapacity, int normCapacity) {
            // 如果当前ChunkList有Chunk可以分配 或者 请求的大小符合ChunkList的范围
            if (head == null || normCapacity > maxCapacity) {
                return false;
            }
    
            // 遍历ChunkList中的Chunk进行分配
            for (PoolChunk<T> cur = head;;) {
                long handle = cur.allocate(normCapacity);
                if (handle < 0) {// 分配失败,找下一个
                    cur = cur.next;
                    if (cur == null) {
                        return false;
                    }
                } else {
                    cur.initBuf(buf, handle, reqCapacity);// 初始化buf,将buf和Chunk关联
                    if (cur.usage() >= maxUsage) {// 分配好之后,如果大于当前ChunkList,那么移动到下一个ChunkList
                        remove(cur);
                        nextList.add(cur);
                    }
                    return true;
                }
            }
        }
    

    添加Chunk

    当一个Chunk要进入ChunkList,要调用add方法

        void add(PoolChunk<T> chunk) {
            // 如果说加入的这个chunk的使用率大于当前ChunkList最大的使用率,那么肯定不能加入当前的ChunkList
            // 要加入下一个ChunkList中,直到找到合适的ChunkList
            if (chunk.usage() >= maxUsage) {
                nextList.add(chunk);
                return;
            }
            add0(chunk);
        }
        // 设置Chunk所属的ChunkList,并加入到head前面,并将该Chunk设置为新的head
        void add0(PoolChunk<T> chunk) {
            chunk.parent = this;
            if (head == null) {
                head = chunk;
                chunk.prev = null;
                chunk.next = null;
            } else {
                chunk.prev = null;
                chunk.next = head;
                head.prev = chunk;
                head = chunk;
            }
        }
    

    释放Chunk

    当从Chunk分配的内存使用完后,在调用Chunk的free方法释放内存之后,这个Chunk的使用率会发生变化,可能需要移动该Chunk

        boolean free(PoolChunk<T> chunk, long handle) {
            chunk.free(handle);
            // //如果释放之后,使用率低于该ChunkList的最低使用率,则从该ChunkList中移除,添加到前面的ChunkList
            if (chunk.usage() < minUsage) {
                remove(chunk);
                // 在链表上寻找使用率相符的ChunkList添加
                return move0(chunk);
            }
            return true;
        }
    

    相关文章

      网友评论

          本文标题:Netty源码分析----PoolChunkList

          本文链接:https://www.haomeiwen.com/subject/rkrlkftx.html