【Netty 专栏】深入浅出 Netty 内存管理 PoolChunkList

本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

原文链接:blog.ouyangsihai.cn >> 【Netty 专栏】深入浅出 Netty 内存管理 PoolChunkList

点击上方“芋道源码”,选择“置顶公众号”

技术文章第一时间送达!

摘要: 原创出处 https://www.jianshu.com/p/a1debfe4ff02 「占小狼」欢迎转载,保留摘要,谢谢!

  • PoolChunkList

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

PoolChunkList

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


final class PoolChunkListT implements PoolChunkListMetric {

    private final PoolChunkList nextList;
    private final int minUsage;
    private final int maxUsage;

    private PoolChunk head;
    private PoolChunkList prevList;
    ...
}

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

Paste_Image.png

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


boolean allocate(PooledByteBuf buf, int reqCapacity, int normCapacity) {
    if (head == null) {
        return false;
    }

    for (PoolChunk 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 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链表中前后移动。

如果你对 Dubbo 感兴趣,欢迎加入我的知识星球一起交流。

【Netty 专栏】深入浅出 Netty 内存管理 PoolChunkList

目前在知识星球(https://t.zsxq.com/2VbiaEu)更新了如下 Dubbo 源码解析如下:

01. 调试环境搭建

02. 项目结构一览

  1. 配置 Configuration

04. 核心流程一览

05. 拓展机制 SPI

  1. 线程池

07. 服务暴露 Export

08. 服务引用 Refer

  1. 注册中心 Registry

  2. 动态编译 Compile

  3. 动态代理 Proxy

  4. 服务调用 Invoke

  5. 调用特性

  6. 过滤器 Filter

  7. NIO 服务器

  8. P2P 服务器

  9. HTTP 服务器

  10. 序列化 Serialization

  11. 集群容错 Cluster

  12. 优雅停机

  13. 日志适配

  14. 状态检查

  15. 监控中心 Monitor

  16. 管理中心 Admin

  17. 运维命令 QOS

  18. 链路追踪 Tracing

一共 60 篇++

源码不易↓↓↓

点赞****支持老艿艿↓↓

本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

原文链接:blog.ouyangsihai.cn >> 【Netty 专栏】深入浅出 Netty 内存管理 PoolChunkList


 上一篇
【Netty 专栏】深入浅出 Netty 内存管理 PoolArena 【Netty 专栏】深入浅出 Netty 内存管理 PoolArena
点击上方“芋道源码”,选择“置顶公众号” 技术文章第一时间送达! 摘要: 原创出处 https://www.jianshu.com/p/4856bd30dd56 「占小狼」欢迎转载,保留摘要,谢谢! PoolArena 前面分别分析
2021-04-05
下一篇 
【Netty 专栏】深入浅出 Netty 内存管理 PoolSubpage 【Netty 专栏】深入浅出 Netty 内存管理 PoolSubpage
源码精品专栏 精尽 Dubbo 原理与源码专栏( 已经完成 69+ 篇,预计总共 75+ 篇 ) 中文详细注释的开源项目 Java 并发源码合集 RocketMQ 源码合集 Sharding-JDBC 源码解析合集 Spring MVC
2021-04-05