美文网首页
PoolChunkList

PoolChunkList

作者: Pillar_Zhong | 来源:发表于2019-08-01 21:23 被阅读0次

    概要

    在Netty中, PoolArena将内存分为很多PoolChunk进行管理. 通过多个PoolChunkList根据PoolChunk的使用率进行分组保存,并将动态的移动至对应的PoolChunkList中

    在PoolArena中根据使用率分如下几组PoolChunkList

    private final PoolChunkList<T> q050; //存储内存利用率50-100%的PoolChunk
    private final PoolChunkList<T> q025; //存储内存利用率25-75%的PoolChunk
    private final PoolChunkList<T> q000; //存储内存利用率1-50%的PoolChunk
    private final PoolChunkList<T> qInit; //存储内存利用率0-25%的PoolChunk
    private final PoolChunkList<T> q075; //存储内存利用率75-100%的PoolChunk
    private final PoolChunkList<T> q100; //存储内存利用率100%的PoolChunk
    
    q100 = new PoolChunkList<T>(null, 100, Integer.MAX_VALUE, chunkSize);
    q075 = new PoolChunkList<T>(q100, 75, 100, chunkSize);
    q050 = new PoolChunkList<T>(q075, 50, 100, chunkSize);
    q025 = new PoolChunkList<T>(q050, 25, 75, chunkSize);
    q000 = new PoolChunkList<T>(q025, 1, 50, chunkSize);
    qInit = new PoolChunkList<T>(q000, Integer.MIN_VALUE, 25, chunkSize);
    
    q100.prevList(q075);
    q075.prevList(q050);
    q050.prevList(q025);
    q025.prevList(q000);
    q000.prevList(null);
    qInit.prevList(qInit);
    
    img

    PoolChunkList类主要属性如下所示:

    // 下一个ChunkList
    private final PoolChunkList<T> nextList;
    // 最小内存使用率
    private final int minUsage;
    // 最大内存使用率
    private final int maxUsage;
    private final int maxCapacity;
    // 头节点
    private PoolChunk<T> head;
    // 上一个ChunkList
    private PoolChunkList<T> prevList;
    
    img

    构造方法

    PoolChunkList(PoolChunkList<T> nextList, int minUsage, int maxUsage, int chunkSize) {
        assert minUsage <= maxUsage;
        this.nextList = nextList;
        this.minUsage = minUsage;
        this.maxUsage = maxUsage;
        // 该list所能分配的最大容量
        maxCapacity = calculateMaxCapacity(minUsage, chunkSize);
    }
    
    private static int calculateMaxCapacity(int minUsage, int chunkSize) {
        minUsage = minUsage0(minUsage);
    
        if (minUsage == 100) {
            return 0;
        }
        // 计算一个chunk在除去最小的使用率的情况下所能分配的最大空间
        // Q25的maxCapacity=chunkSize*75%
        return  (int) (chunkSize * (100L - minUsage) / 100L);
    }
    

    添加

    void add(PoolChunk<T> chunk) {
        // 看当前chunk的使用率是否超过了最大值, 加到下一个list
        if (chunk.usage() >= maxUsage) {
            nextList.add(chunk);
            return;
        }
        add0(chunk);
    }
    
    void add0(PoolChunk<T> chunk) {
        // 在chunk中保存所属的chunlist
        chunk.parent = this;
        // 如果还没有head, chunk来
        if (head == null) {
            head = chunk;
            chunk.prev = null;
            chunk.next = null;
        } else {
            // 将这个chunk加到list里面作为新的head
            chunk.prev = null;
            chunk.next = head;
            head.prev = chunk;
            head = chunk;
        }
    }
    

    删除

    private void remove(PoolChunk<T> cur) {
        if (cur == head) {
            // 让下一个接替head
            head = cur.next;
            if (head != null) {
                head.prev = null;
            }
        } else {
            // 将cur前后解绑
            PoolChunk<T> next = cur.next;
            cur.prev.next = next;
            if (next != null) {
                next.prev = cur.prev;
            }
        }
    }
    

    分配

    boolean allocate(PooledByteBuf<T> buf, int reqCapacity, int normCapacity) {
        // 如果没有head或超过最大容量,那么返回false,表示分配失败
        if (head == null || normCapacity > maxCapacity) {
            return false;
        }
    
        // 遍历chunklist
        for (PoolChunk<T> cur = head;;) {
            // 去chunk中申请空间
            long handle = cur.allocate(normCapacity);
            // 如果handle<0, 说明申请失败, 继续滚动到下一个chunk循环
            if (handle < 0) {
                cur = cur.next;
                if (cur == null) {
                    return false;
                }
            } else {
                // 如果申请成功, 那么将内存空间与ByteBuf进行绑定
                cur.initBuf(buf, handle, reqCapacity);
                // 接着计算当前chunk的使用率,如果超过最大阈值,那么从当前list中删除,并移动到下个list
                // 也就是升舱处理
                if (cur.usage() >= maxUsage) {
                    remove(cur);
                    nextList.add(cur);
                }
                return true;
            }
        }
    }
    

    释放

    boolean free(PoolChunk<T> chunk, long handle) {
        // 释放该chunk对应的handle持有的内存空间
        chunk.free(handle);
        // 如果小于最下,那么同理需要降级处理
        if (chunk.usage() < minUsage) {
            remove(chunk);
            // Move the PoolChunk down the PoolChunkList linked-list.
            return move0(chunk);
        }
        return true;
    }
    

    移动

    private boolean move0(PoolChunk<T> chunk) {
        if (prevList == null) {
            assert chunk.usage() == 0;
            return false;
        }
        return prevList.move(chunk);
    }
    
    private boolean move(PoolChunk<T> chunk) {
        // 接着move0的上下文,这里已经到了prevlist, 判断是否满足该list的使用率条件
        assert chunk.usage() < maxUsage;
        
        // 如果还是低于该区的最小,那么继续降级
        if (chunk.usage() < minUsage) {
            return move0(chunk);
        }
    
        // 否则add到该list
        add0(chunk);
        return true;
    }
    
    

    相关文章

      网友评论

          本文标题:PoolChunkList

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