ByteBuf池化技术Part II

第一部分提到了ByteBuf的内存结构,这儿有几点需要补充并在某些点展开说明

大对象的处理

当申请的分配对象超过Chunk容量大小,Netty就不在使用池化管理的方式了,在每次请求分配内存时单独创建非池化PoolChunk对象进行管理,当对象释放时整个PoolChunk内存释放。

小对象处理

如果申请的内存空间远小于PageSize的话,按照之前提到的,就需要为每个小ByteBuf对象分配一个Page,这就出现内存浪费和内存碎片的问题,Netty将再把Page细分,Netty 将请求的空间大小向上取最近的 16 的倍数(或 2 的幂),规整后小于 PageSize 的小 Buffer 可分为两类。

  • 微型对象:规整后的大小为 16 的整倍数,如 16、32、48、......、496,一共 31 种大小。
  • 小型对象:规整后的大小为 2 的幂,如 512、1024、2048、4096,一共 4 种大小。

这样的话,当向系统申请小对象存储空间时,Netty会先从Poolchunk中申请空闲的Page,同一个Page分为相同大小的buffer,这些Page用PoolSubpage对象进行封装,PoolSubpage内部会记录它自己能分配的小buffer的的规格,可用内存数量,并通过bitmap的方式记录各个小内存的使用情况。虽然这种方案不能完美消灭内存碎片,但是却在很大程度上减少了内存浪费。

基于二叉平衡树的算法结构

上个章节提到Netty中的池化技术实现是基于分层的结构,具体到数据结构的话就是用二叉平衡树进行的实现 当需要创建一个给定大小的ByteBuf,算法需要在PoolChunk中大小为chunkSize的内存中,找到第一个能够容纳申请分配内存的位置

为了方便快速查找chunk中能容纳请求内存的位置,算法构建一个基于byte数组(memoryMap)存储的完全平衡树,该平衡树的多个层级深度,就是前面介绍的按照不同粒度对chunk进行多层分组:

当申请分配大小为chunkSize/2^k的内存,在平衡树高度为k的层级中,从左到右搜索第一个空闲节点

数组的使用域从index = 1开始,将平衡树按照层次顺序依次存储在数组中,depth = n的第1个节点保存在memoryMap[2^n] 中,第2个节点保存在memoryMap[2^n+1]中,以此类推(下图代表已分配chunkSize/2)

可以根据memoryMap[id]的值得出节点的使用情况,memoryMap[id]值越大,剩余的可用内存越少

  • memoryMap[id] = depth_of_id:id节点空闲, 初始状态,depth_of_id的值代表id节点在树中的深度
  • memoryMap[id] = maxOrder + 1:id节点全部已使用,节点内存已完全分配,没有一个子节点空闲
  • depth_of_id < memoryMap[id] < maxOrder + 1:id节点部分已使用 ,memoryMap[id] 的值 x,代表id的子节点中,第一个空闲节点位于深度x,在深度[depth_of_id, x)的范围内没有任何空闲节点 (引用链接:juejin.cn/post/684490...
相关推荐
漫步者TZ1 小时前
【Netty系列】解决TCP粘包和拆包:LengthFieldBasedFrameDecoder
java·网络协议·tcp/ip·netty
安徽杰杰8 小时前
智慧赋能:移动充电桩的能源供给革命与便捷服务升级
netty
安徽杰杰12 小时前
智慧赋能:新能源汽车充电桩应用现状与管理升级方案
netty
触角云科技5 天前
智慧充电桩数字化管理平台:环境监测与动态数据可视化技术有哪些作用?
netty
猫咪老师QAQ5 天前
Netty 实战篇:Netty RPC 框架整合 Spring Boot,迈向工程化
netty
猫咪老师QAQ5 天前
Netty 实战篇:为 Netty RPC 框架引入调用链追踪,实现链路透明化
netty
漫步者TZ6 天前
【Netty系列】实现HTTP文件服务器
http·网络编程·netty
猫咪老师QAQ6 天前
Netty 实战篇:构建简易注册中心,实现服务发现与调用路由
netty
触角云科技6 天前
充电便捷,新能源汽车移动充电服务如何预约充电
netty
漫步者TZ6 天前
【Netty系列】Reactor 模式 2
设计模式·netty