点击上方“芋道源码”,选择“置顶公众号”
技术文章第一时间送达!
摘要: 原创出处 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 感兴趣,欢迎加入我的知识星球一起交流。

目前在知识星球(https://t.zsxq.com/2VbiaEu)更新了如下 Dubbo 源码解析如下:
01. 调试环境搭建
02. 项目结构一览
- 配置 Configuration
04. 核心流程一览
05. 拓展机制 SPI
- 线程池
07. 服务暴露 Export
08. 服务引用 Refer
注册中心 Registry
动态编译 Compile
动态代理 Proxy
服务调用 Invoke
调用特性
过滤器 Filter
NIO 服务器
P2P 服务器
HTTP 服务器
序列化 Serialization
集群容错 Cluster
优雅停机
日志适配
状态检查
监控中心 Monitor
管理中心 Admin
运维命令 QOS
链路追踪 Tracing
…
一共 60 篇++
源码不易↓↓↓↓↓
点赞****支持老艿艿↓↓