深入浅出Netty内存管理 PoolChunkList

前面两篇分别分析了PoolChunk和PoolSubpage的实现,本文主要分析管理PoolChunk生命周期的PoolChunkList。
1、深入浅出Netty内存管理 PoolChunk
2、深入浅出Netty内存管理 PoolSubpage

PoolChunkList

PoolChunkList负责管理多个chunk的生命周期,在此基础上对内存分配进行进一步的优化。

final class PoolChunkList<T> implements PoolChunkListMetric {
    
    private final PoolChunkList<T> nextList;
    private final int minUsage;
    private final int maxUsage;

    private PoolChunk<T> head;
    private PoolChunkList<T> prevList;
    ...
}

从代码实现可以看出,每个PoolChunkList实例维护了一个PoolChunk链表,自身也形成一个链表,为何要这么实现?

Paste_Image.png

随着chunk中page的不断分配和释放,会导致很多碎片内存段,大大增加了之后分配一段连续内存的失败率,针对这种情况,可以把内存使用率较大的chunk放到PoolChunkList链表更后面,具体实现如下:

boolean allocate(PooledByteBuf<T> buf, int reqCapacity, int normCapacity) {
    if (head == null) {
        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);
            if (cur.usage() >= maxUsage) {   // (1)
                remove(cur);
                nextList.add(cur);
            }
            return true;
        }
    }
}

假设poolChunkList中已经存在多个chunk。当分配完内存后,如果当前chunk的使用量超过maxUsage,则把该chunk从当前链表中删除,添加到下一个链表中。

但是,随便chunk中内存的释放,其内存使用率也会随着下降,当下降到minUsage时,该chunk会移动到前一个列表中,实现如下:

boolean free(PoolChunk<T> chunk, long handle) {
    chunk.free(handle);
    if (chunk.usage() < minUsage) {
        remove(chunk);
        if (prevList == null) {
            assert chunk.usage() == 0;
            return false;
        } else {
            prevList.add(chunk);
            return true;
        }
    }
    return true;
}

从poolChunkList的实现可以看出,每个chunkList的都有一个上下限:minUsage和maxUsage,两个相邻的chunkList,前一个的maxUsage和后一个的minUsage必须有一段交叉值进行缓冲,否则会出现某个chunk的usage处于临界值,而导致不停的在两个chunk间移动。

所以chunk的生命周期不会固定在某个chunkList中,随着内存的分配和释放,根据当前的内存使用率,在chunkList链表中前后移动。

END。
我是占小狼。
在魔都艰苦奋斗,白天是上班族,晚上是知识服务工作者。
如果读完觉得有收获的话,记得关注和点赞哦。
非要打赏的话,我也是不会拒绝的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 前面分别分析了PoolChunk、PoolSubpage和PoolChunkList,本文主要分析PoolAren...
    美团Java阅读 16,415评论 1 20
  • Netty中有一个主要的特点,就是ByteBuf的实现, 由于NIO中java.nio.ByteBuf中只有pos...
    桥头桥尾阅读 1,136评论 0 2
  • 概述 我们都知道一个进程是与其他进程共享CPU和内存资源的。正因如此,操作系统需要有一套完善的内存管理机制才能防止...
    SylvanasSun阅读 3,896评论 0 25
  • 一气呵成将余华的《活着》看完了。当一个人的命运、故事,让我用旁人的眼光将它迅速看完时,心情是那样沉重。合上书,眼前...
    沐伊520阅读 518评论 0 1
  • 写给你懂我 懒得去写什么 我懒得去懂我 像你一样 忧伤是心里的主调 带着缠绵的灯光一样懒 你说我消极 好像 是懒得...
    青早阅读 244评论 0 0