Netty中的PooledByteBuf池化原理剖析

news2024/12/27 13:19:46

PooledByteBuf

PooledByteBuf是池化的ByteBuf,提高了内存分配与释放的速度,它本身是一个抽象泛型类,
有三个子类:PooledDirectByteBuf、PooledHeapByteBuf、PooledUnsafeDirectByteBuf.

Jemalloc算法

Netty的PooledByteBuf采用与jemalloc一致的内存分配算法。基本思路可用这样的情景类比,想象一下电商的配送流程。当顾客采购小件商品(比如书籍)时,直接从同城仓库送出;当顾客采购大件商品(比如电视)时,从区域仓库送出;当顾客采购超大件商品(比如汽车)时,则从全国仓库送出。Netty的分配算法与此相似。Netty中,Tiny和Small类型的请求都首先从同城仓库(ThreadCache-tcache)送出;如果同城仓库没有,则会从区域。仓库(PoolArena)送出,Normal类型的请求则从区域仓库(PoolArena)送出,Huge类型的请求则从全国仓库(系统内存)送出。
Netty中规定:

  • 1.内存分配的最小单位为16B
  • 2.小于512B的请求为Tiny,512B<x<8KB(PageSize)的请求为Small,8KB<=X<=16MB(ChunkSize)的请求为Normal,大于16MB(ChunkSize)的请求为Huge
  • 3.Tiny、Small、Normal、Huge中还有细层级,小于Tiny的请求以16B为起点每次增加16B作为一个层级,也就是
    Tiny中还有16B、32B、48B、…480B、496B的层级
    其他类型的则是翻倍:
    Small中还有512B、1KB、2KB、4KB的层级
    Normal中还有8KB、16KB、32KB…8MB、16MB的层级
    Huge中还有32MB、64MB…的层级
  • 4.不管请求的大小,都会将向上规范化,比如:请求分配511B、512B、513B,将依次规范化为512B、512B、1KB
    为了提高内存分配效率并减少内部碎片,jemalloc算法将Arena切分为小块Chunk,根据每块的内存使用率又将小块组合为以下集中状态QINIT,Q0,Q25,Q50,Q75,Q100。Chunk块可以在这几种状态间随着内存使用率的变化进行转移,内存使用率和状态转移如图所示。
    在这里插入图片描述
    其中横轴表示内存使用率(百分比),纵轴表示状态,可以看到:
    QINIT的内存使用率为[0,25),Q0为(0,50),Q100为[100,100]等等。
    Chunk的初始状态为QINIT,当使用率达到25时转移到Q0状态,再次达到50时转移到Q25,依次类推直到Q100;当内存释放时又从Q100转移到Q75,直到Q0状态且内存使用率为0时,该Chunk从Arena中删除。像qinit、q000、q075因为本身要维护很多Chunk块,所以内部是以链表的形式来组织Chunk块,同时qinit、q000、q075本身又组织为一个近似的双向链表,如图所示。
    在这里插入图片描述
    虽然已将Arena切分成小块的Chunk,但实际上Chunk是相当大的内存块,在Netty中默认使用16MB。为了进一步提高内存利用率,并减少内部碎片,需要继续将Chunk切分为小的快Page.一个典型的切换将Chunk切分为2048块,可知Page的大小为:16MB/2048=8KB.一个好的内存分配算法,应使得已分配内存块尽可能保持连续,这将大大减少内部碎片,由此jemalloc使用伙伴分配算法尽可能提高连续性。伙伴分配算法的基本思想是:
    我们知道一个Chunk切分为2048块Page,将这些Page作为叶子节点,然后组织起一个满二叉树,然后按层分配满足要求的内存块。以待分配序列8KB、16KB、8KB为例分析分配过程(每个Page大小8KB):
  • 8KB–需要一个Page,第11层满足要求,故分配2048节点即Page0
  • 16KB-需要两个Page,故需要在第10层进行分配,而1024节点的子节点2048已分配,从左到右找到满足要求的1025节点,故分配节点1025即Page2和Page3
  • 8KB–需要一个Page,第11层满足要求,2048已分配,从左到右找到2049节点即Page1进行分配。分配结束后,已分配连续的Page0-Page3,这样的连续内存块,大大减少内部碎片并提高内存使用率,为了实现伙伴算法,Netty中使用了memoryMap和depthMap来表示两棵二叉树,其中MemoryMap存放分配信息,depthMap存放节点的高度信息

在这里插入图片描述

我们在前面说过,一个page是8KB,但是Netty又支持Tiny、Small这种小于8KB,最小可达16B的内存分配请求,每次都分配一个page,很浪费。为了进一步切分Page成更小的SubPage,SubPage是jemalloc中内存分配的最小单位,不能再进行切分.SubPage切分的单位并不固定,以第一次请求分配的大小为单位(最小切分单位为16B).比如,第一次请求分配32B,则Page按照32B均等切分为256块;第一次请求请求16B,则Page按照16B均等切分512块。为了便于内存分配和管理,根据SubPage的切分单位进行分组,对每个组而言,Arena会以双向链表的形式进行管理。那么根据切分的单位的大小和Page的大小,SubPage分为两类:tinySubPagePools和smallSubPagePools,tinySubPage中的subPage的大小,从16字节到496个字节,共有32个元素,smallSubPagePools则有512字节、1024、2048、4096共4个元素。如图所示。

在Arena数量上,为了减少各个线程进行内存分配时竞争,Netty中会有多个Arena,默认的数量与处理器的个数有关,线程首次分配内存时,首先会为其分配一个固定的Arena
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
左图表示每个节点的编号,注意从1开始,省略0是因为这样更容易计算父子关系:子节点加倍,父节点减半,比如512的子节点为1024=512 *2.右图表示每个节点的深度,注意从0开始。在代表二叉树的数组中,左图中节点上的数字作为数组索引即id,右图节点上的数字作为值。初始
状态时,memoryMap和depthMap相等,可知一个id为512节点的初始值为9,memoryMap[512]=depthMap[512]=9,depthMap的值初始化后不再改变,memoryMap的值随着节点分配而改变,当一个节点被分配以后,
该节点的值设置为12(最大高度+1)表示不可用,并且会更新祖先节点的值。
在这里插入图片描述
分配过程如下:
4号节点被完全分配,将高度值设置为12表示不可用。
4号节点的父亲节点即2号节点,将高度值更新为两个子节点的较小值;其他祖先节点亦然,直到高度值更新到根节点,可推知,memoryMap数组的值有如下三种情况:

  • memoryMap[id]=depthMap[id] – 该节点没有被分配
  • memoryMap[id] > depthMap[id] – 至少有一个子节点被分配,不能再分配该高度满足的内存,但可以根据实际分配较小一些的内存,比如,上图中分配了4号子节点的2号节点,值从1更新为2,表示该节点不能再分配8MB的只能最大分配4MB内存,因为分配了4号节点后只剩下5号节点可用。
  • memoryMap[id] = 最大高度 +1 (本例中12) – 该节点及其子节点已被完全分配,没有剩余空间。

PoolThreadCache.

同时在Netty中为了提升性能,并不会一开始就从PoolArena中分配,因为Arena为几个线程共享,而是先从每个线程自己的PoolThreadCache中去获取。当然开始的是偶,这些Cache里面都是没有值的,要先从PoolArena中获取,当释放Buf的时候,才会把之前分配的内存大小放到该cache里面,当下次申请内存的时候,就会先从PoolThreadCache中找。
PoolThreadCache中则维护了6个这样的线程缓存区域,3个堆内存相关,3个直接内存相关,分别对应着三种
分配内存的大小small类型的数组的大小为4,而tiny、normal数组的大小分别为32、3,smallSubPageHeapCache的数组长度为4,依次缓存[512K,1024K,2048K,4096K]大小的缓存,每个元素对应的缓存
queue中的元素个数不能超过256个,而tinySubPageHeapCaches数组缓存的是[16B,32B,…,496B]大小的内存块,每个元素,对应的缓存queue中元素个数不能超过512个,normalHeapCaches数组结构相同,但是只缓存[8K,16K,32K]大小的内存块,每个元素对应的缓存queue中元素个数不超过64个。每一个MemoryRegionCache中又包含一个队列。队列中的每个元素类型为Entry,Entry中又包含了一个PoolChunk,以方便对内存的管理
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1461690.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SICTF Round#3 の WP

Misc 签到 SICTF{1f4ce05a-0fed-42dc-9510-6e76dff8ff53} Crypto [签到]Vigenere 附件内容&#xff1a; Gn taj xirly gf Fxgjuakd, oe igywnd mt tegbs mnrxxlrivywd sngearbsw wakksre. Bs kpimj gf tank, it bx gur bslenmngn th jfdetagur mt ceei yze Ugnled Lystel t…

NFC三大工作模式及其在物联网应用实例

NFC支持三种通信模式&#xff1a;读写模式、点对点模式和卡模拟模式。在此三种模式下&#xff0c;都仅需简单点击便可启动传输。 在读写模式下&#xff0c;系统执行非接触式读写功能。该系统的NFC芯片与内置NFC的设备-诸如非接触式智能卡、NFC标签或具有NFC功能的智能手机&…

pylint、pyreverse

文章目录 pylintpyreverse pylint github : https://github.com/pylint-dev/pylint官网&#xff1a;https://www.pylint.org文档&#xff1a;https://pylint.readthedocs.io/en/latest/ Pylint 是一个 Python 代码分析工具&#xff0c;它分析 Python 代码中的语法错误&#xf…

【代码随想录python笔记整理】第十二课 · 位置互换

前言:本笔记仅仅只是对内容的整理和自行消化,并不是完整内容,如有侵权,联系立删。 一、变量交换的实现 这节我们讨论一个简单的问题——怎么交换两个变量的值。比如说,一个瓶子里是水,一个瓶子里是油,想要将两个瓶子中的东西互换,我们应该怎么做呢?要实现上述过程,我们…

leetcode hot100 完全平方数

本题中&#xff0c;是给一个整数n&#xff0c;让用完全平方数凑出这个整数&#xff0c;注意&#xff0c;题中给了n的范围&#xff0c;是大于等于1的&#xff0c;也就是说&#xff0c;dp[0]我们可以先不考虑。 整个问题可以抽象成完全背包问题的变形形式&#xff0c;物品就是这…

免费听歌软件,音乐搜索APP:掌中的音乐宝库,为您的音乐生活增添色彩

引言 在数字音乐的浪潮中&#xff0c;我们通常会想到QQ音乐、虾米、网易云音乐等主流平台APP。然而&#xff0c;这些商业软件在为用户提供服务的同时&#xff0c;也不可避免地伴随着一些限制和不尽如人意的地方&#xff0c;如曲库有限、音质不尽如人意或广告干扰或会员才能听歌…

TypeScript中的keyof、typeof、in

概览 TypeScript中的keyof、typeof、in在我们日常工作中经常用到&#xff0c;但也容易遗忘&#xff0c;现详细梳理其用法及使用场景 一. 抛出问题 const getFormatData (initData) > { const data [];// 部分字段取值需保留小数点后两位const formatKeys [priceUntax…

频段划分学习射频知识的意义

一、射频电路设计与低频电路设计的不同点 随着频率提高&#xff0c;相应电磁波的波长与变得可与分立电路元件的尺寸相比拟时&#xff0c;电阻、电容和电感这些元件的电响应&#xff0c;将偏离他们的理想频率特性。以 WIFI 2.4G 频段为例&#xff0c;当频率为 2437MHz&#xff0…

年收入 100 万,不敢生孩子

原文连接&#xff1a; 年收入 100 万&#xff0c;不敢生孩子 今日热帖&#xff0c;有网友发帖称&#xff1a;互联网大头兵夫妇&#xff0c;两个人都 30 了&#xff0c;老公 xhs 后端年包 80&#xff0c;我私企年薪 20 左右&#xff0c;老家三线城市有房。 本来今年要孩子了&am…

花了钱的ChatGPT4.0在绘画方面的能力如何?Sora也能work吗

花了钱的ChatGPT4.0在绘画方面的能力如何&#xff1f;Sora也能work吗 关注微信公众号 DeepGoAI 计算机杂谈及深度学习记录&分享 众所周知 AI绘图是4.0收费的一大卖点 网上也有许多反复训练ChatGPT的段子视频 让人工智能无语 网友直呼 “未来人工智能统治世界了&…

016—pandas 分析近100年圣诞节日期分布

需求&#xff1a; 利用Pandas 分析近100年圣诞节的星期分布&#xff0c;目的是知道圣诞节都在星期几&#xff0c;哪个星期多些。 思路&#xff1a; 用 pd.date_range 生成 100 年日期数据 筛选出12月25日的所有日期 将日期转换为星期几 统计重复值的数量 绘图 二、…

【JAVA高级面试题】运用锁机制实现一个自定义的阻塞队列

文章目录 前言实战演示写在最后 前言 前几天看见一个高级Java面试题&#xff0c;我觉得很有代表意义。既考察了面试者的基本锁机制运用&#xff0c;也了解了阻塞队列的产生实现原理。先分享出来&#xff0c;以供鉴赏。 面试题&#xff1a;实现一个自定义的阻塞队列&#xff0c…

【C++语法基础】4.分支和循环结构(✨新手推荐阅读)

前言 在C编程中&#xff0c;分支和循环结构是控制程序流程的基本工具。分支结构允许程序根据特定条件执行不同的代码块&#xff0c;而循环结构则允许程序重复执行某个代码块。 分支结构 if 语句 if 语句是最基本的分支结构&#xff0c;它根据条件的真假来决定是否执行某段代…

Linux实验记录:使用LNMP架构部署动态网站环境

前言&#xff1a; 本文是一篇关于Linux系统初学者的实验记录。 参考书籍&#xff1a;《Linux就该这么学》 实验环境&#xff1a; VmwareWorkStation 17——虚拟机软件 RedHatEnterpriseLinux[RHEL]8——红帽操作系统 备注&#xff1a; LNMP动态网站部署架构是一套由&…

Linux 性能分析工具汇总

Linux 性能分析工具汇总 出于对Linux操作系统的兴趣&#xff0c;以及对底层知识的强烈欲望&#xff0c;因此整理了这篇文章。本文也可以作为检验基础知识的指标&#xff0c;另外文章涵盖了一个系统的方方面面。如果没有完善的计算机系统知识&#xff0c;网络知识和操作系统知识…

(done) 两个矩阵 “相似” 是什么意思?

参考视频&#xff1a;https://www.bilibili.com/video/BV1zu411673J/?spm_id_from333.337.search-card.all.click&vd_source7a1a0bc74158c6993c7355c5490fc600 参考资料&#xff1a;https://baike.baidu.com/item/%E7%9B%B8%E4%BC%BC%E7%9F%A9%E9%98%B5/10369874?frge_a…

离线环境解决IDEA连接数据库报需下载驱动的问题 Download missing driverfiles

去外网电脑上把这个目录下的MySQL ConnectorJ文件夹整体拷贝的内网电脑上就ok了&#xff01; C:\Users\like12\AppData\Roaming\JetBrains\IntelliJIdea2021.2\jdbc-drivers 参考&#xff1a;IDEA Download missing driver files 下载失败解决方法-CSDN博客

开发一款招聘小程序需要具备哪些功能?

随着时代的发展&#xff0c;找工作的方式也在不断变得简单&#xff0c;去劳务市场、人才市场的方式早就已经过时了&#xff0c;现在大多数年轻人都是直接通过手机来找工作。图片 找工作类的平台不但能扩大企业的招聘渠道&#xff0c;还能节省招聘的成本&#xff0c;方便求职者进…

7. Qt添加滑动条

前言&#xff1a; 添加一个这样的滑条&#xff0c;双方关联自动修改,也提供代码创建方式 技能&#xff1a; QSpinBox QSlider 方式一 Qt 的图形化编程&#xff08;用ui文件&#xff0c;非常简单&#xff09; 1.Spin Box 首先找到显示数字的这个部分。是input widget->sp…

useGeneratedKeys=“true” keyProperty=“id”

useGeneratedKeys“true” keyProperty“id” 这个注解在xml文件的insert方法中&#xff0c;可以用于返回主键值&#xff1b; 并且useGeneratedKeys参数只针对 insert 语句生效&#xff0c;默认为 false&#xff1b;