PoolChunkList

Posted grimreaper

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PoolChunkList相关的知识,希望对你有一定的参考价值。

概述(Motivation)

chunklist

实现细节(Modification)

主要成员

private final PoolArena<T> arena;
    private final PoolChunkList<T> nextList;
    private final int minUsage;
    private final int maxUsage;
    // poolChunkList存放的都是同一种chunk,所以初始化的时候根据chunkSize*(1-minUsage)
    // 因为此List中的chunk使用率最低是minUsage,所以最多只能分配(1-minUsage)
    private final int maxCapacity;
    private PoolChunk<T> head;

    // This is only update once when create the linked like list of PoolChunkList in PoolArena constructor.
    private PoolChunkList<T> prevList;

分配函数

    boolean allocate(PooledByteBuf<T> buf, int reqCapacity, int normCapacity) {
        if (head == null || normCapacity > maxCapacity) {
            // Either this PoolChunkList is empty or the requested capacity is larger then the capacity which can
            // be handled by the PoolChunks that are contained in this PoolChunkList.
            return false;
        }

        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);
                // 超过使用率会将chunk转移到下一个list
                if (cur.usage() >= maxUsage) {
                    remove(cur);
                    nextList.add(cur);
                }
                return true;
            }
        }
    }

释放函数

 boolean free(PoolChunk<T> chunk, long handle) {
        chunk.free(handle);
        // 如果释放后当前使用量低于限定值,移动到前一个
        if (chunk.usage() < minUsage) {
            // chunkList自身指针的操作去除该chunk结点
            remove(chunk);
            // Move the PoolChunk down the PoolChunkList linked-list.
            // 该chunk进行移动
            return move0(chunk);
        }
        return true;
    }

     /**
     * Moves the {@link PoolChunk} down the {@link PoolChunkList} linked-list so it will end up in the right
     * {@link PoolChunkList} that has the correct minUsage / maxUsage in respect to {@link PoolChunk#usage()}.
     */
    private boolean move0(PoolChunk<T> chunk) {
        if (prevList == null) {
            // There is no previous PoolChunkList so return false which result in having the PoolChunk destroyed and
            // all memory associated with the PoolChunk will be released.
            // 调用者的逻辑会将该chunk进行destroy处理
            assert chunk.usage() == 0;
            return false;
        }
        return prevList.move(chunk);
    }

  private boolean move(PoolChunk<T> chunk) {
        assert chunk.usage() < maxUsage;

        if (chunk.usage() < minUsage) {
            // Move the PoolChunk down the PoolChunkList linked-list.
            return move0(chunk);
        }

        // PoolChunk fits into this PoolChunkList, adding it here.
        // chunkList自身指针的操作加入该chunk结点
        add0(chunk);
        return true;
    }

分配顺序

之前在poolArena中,分配的顺序是50->25->00->init->75。

网上基本就一个观点。。高峰期分配内存容易释放掉不会堆积。

我觉得一个网络一般是稳定,那么意味着我们希望保持一个高使用率的内存,避免浪费,所以从50起是一个适中值堆积起一些常用的内存。当然50确实是个适中值,基本上所有情况下你都可以说中位数是一个合理值。。

综述(Result)

一个描述使用率的链表,将不同使用率的chunk分开,从而能更合理的分配和释放内存。

技术图片

以上是关于PoolChunkList的主要内容,如果未能解决你的问题,请参考以下文章

netty内存算法小析(下)

微信小程序代码片段

VSCode自定义代码片段——CSS选择器

谷歌浏览器调试jsp 引入代码片段,如何调试代码片段中的js

片段和活动之间的核心区别是啥?哪些代码可以写成片段?

VSCode自定义代码片段——.vue文件的模板