jemalloc原理分析

2023-11-13

jemalloc原理分析

转载自http://club.alibabatech.org/article_detail.htm?articleId=36

首先介绍一下jemalloc中的几个核心概念:
1. arena。jemalloc的核心分配管理区域,对于多核系统,会默认分配4*cores的Arena,线程采取轮询的方式来选择相应的arena来进行内存分配。
2. chunk。具体进行内存分配的区域,目前的默认大小是4M。chunk以page(默认为4K)为单位进行管理,每个chunk的前几个page(默认是6个)用于存储后面所有page的状态,比如是否待分配还是已经分配;而后面的所有page则用于进行实际的分配。
3. bin。用来管理各个不同大小单元的分配,比如最小的Bin管理的是8字节的分配,每个Bin管理的大小都不一样,依次递增。jemalloc的bin和ptmalloc的bin的作用类似。在bin里,都会有一个红黑树来维护空闲的run,并且在run里,使用了bitmap来记录了分配状态。
4. run。每个bin在实际上是通过对它对应的正在运行的Run进行操作来进行分配的,一个run实际上就是chunk里的一块区域,大小是page的整数倍,具体由实际的bin来决定,比如8字节的bin对应的run就只有1个page,可以从里面选取一个8字节的块进行分配。在run的最开头会存储着这个run的信息,比如还有多少个块可供分配。
5. tcache。线程对应的私有缓存空间,默认是使用的。因此在分配内存时首先从tcache中找,miss的情况下才会进入一般的分配流程。

jemalloc内存分配

如图每个arena有一个bins数组,根据机器配置不同它的具体结构也不同(由相应的size_class.h中的宏定义决定),在笔者的机器上这个bin数组会管理从8字节一直到3584字节共28种大小的bin,而每个bin会通过它对应的正在运行的run来进行分配。每个tcahe有一个对应的arena,它本身也有一个bins数组(称为tbins),但它长度更大一些(像笔者机器上的tcahe在arena最大的3584字节的bin的基础上,后面还有8个bin,分别对应4K,8K,12K一直到32K。),因为它会缓存一些更大的块;而且它也没有对应的run的概念,因为它只做缓存,只有一个avail数组来存储被缓存的空间的地址。
这里想重点介绍一下chunk与run的关系。之前提到chunk默认是4M,而run是在chunk中进行实际分配的操作对象,每次有新的分配请求时一旦tcache无法满足要求,就要通过run进行操作,如果没有对应的run存在就要新建一个,哪怕只分配一个块,比如只申请一个8字节的块,也会生成一个大小为一个page(默认4K)的run。run的具体大小由它对应的bin决定,但一定是page的整数倍。因此实际上每个chunk就被分成了一个个的run。

可能说到这里读者还是十分模糊,那接下来就介绍一下jemalloc具体是如何进行内存分配的,具体流程如下:
1. 如果请求size不大于arena的最大的bin(笔者机器上是3584字节),那么就通过线程对应的tcache来进行分配。首先确定size的大小属于哪一个tbin,比如2字节的size就属于最小的8字节的tbin,然后查找tbin中有没有缓存的空间,如果有就进行分配,没有则为这个tbin对应的arena的bin分配一个run,然后把这个run里面的部分块的地址依次赋给tcache的对应的bin的avail数组,相当于缓存了一部分的8字节的块,最后从这个availl数组中选取一个地址进行分配;
2. 如果请求size大于arena的最大的bin,同时不大于tcache能缓存的最大块(笔者机器上是32K),也会通过线程对应的tcache来进行分配,但方式不同。首先看tcache对应的tbin里有没有缓存块,如果有就分配,没有就从chunk里直接找一块相应的page整数倍大小的空间进行分配(当这块空间后续释放时,这会进入相应的tcache对应的tbin里);
3. 如果请求size大于tcache能缓存的最大块,同时不大于chunk大小(默认是4M),具体分配和第2类请求相同,区别只是没有使用tcache;
4. 如果请求大于chunk大小,直接通过mmap进行分配。

回收流程大体和分配流程类似,有tcache机制的会将回收的块进行缓存,没有tcache机制的直接回收(不大于chunk的将对应的page状态进行修改,回收对应的run;大于chunk的直接munmap)。需要关注的是jemalloc何时会将内存还给操作系统,因为ptmalloc中存在因为使用top_chunk机制(详见华庭的文章)而使得内存无法还给操作系统的问题。目前看来,除了大内存直接munmap,jemalloc还有两种机制可以释放内存:
1. 当释放时发现某个chunk的所有内存都已经为脏(即分配后又回收)就把整个chunk释放;
2. 当arena中的page分配情况满足一个阈值时对dirty page进行purge(通过调用madvise来进行)。这个阈值的具体含义是该arena中的dirty page大小已经达到一个chunk的大小且占到了active page的1/opt_lg_dirty_mult(默认为1/32)。active page的意思是已经正在使用中的run的page,而dirty page就是其中已经分配后又回收的page。
上述两种机制保证了jemalloc不会出现类似ptmalloc中的内存无法交还给操作系统的问题。
总体而言,jemalloc的设计思想比ptmalloc要简单,却也更先进,tcache的使用保证了分配效率,回收机制也保证了不会出现大量内存无法交还给操作系统的问题,同时将一些管理状态信息单独于分配的空间集中高效存储(大量使用bitmap)提高了内存的使用率。当然由于jemalloc中内存的使用都以page为单位,因此会有一些内部碎片的问题(比如申请5K的空间实际会使用8K的空间),但总体上它仍比ptmalloc占用的内存更少,效率更高。目前redis已经默认使用jemalloc,淘宝的Tengine也已经提供了jemalloc的支持。
参考资料:
1. jemalloc 3.0.0源码
2. 更好的内存管理-jemalloc
3. https://www.owent.net/2013/07/ptmalloctcmalloc%E5%92%8Cjemalloc%E5%86%85%E5%AD%98%E5%88%86%E9%85%8D%E7%AD%96%E7%95%A5%E7%A0%94%E7%A9%B6.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

jemalloc原理分析 的相关文章

  • malloc底层原理实现

    使用过c语言的都知道malloc是一个动态分配内存的函数 还可以通过free释放内存空间 如果我们想分析一下malloc的源码 这其实不是一会就能看懂的 但是我们可以讨论一下malloc的简单实现 在这之前 我们先来看一下虚拟内存空间 虚拟
  • 内核杂谈——页表项存放的是物理地址还是虚拟地址?

    目录 L0 L1 L2 表项 L3 表项 总结 pgd t 不只是物理地址 谈谈对映射的理解 思考 当你不去细细读代码的话 这个问题可能会困扰着你 我们以ARM64四级页表为例 谈谈页表项里藏得是什么 本文讨论的是内核线性映射过程时建立的临
  • STL空间配置器详解-《STL源码剖析第二章学习笔记》

    个人学习笔记 可能有点乱 有理解不对的地方可以给我留言 个人网站www liujianhua xyz STL空间配置器 https www cnblogs com lang5230 p 5556611 html 空间配置器 空间配置器概括
  • 一文读懂 PyTorch 显存管理机制

    点击上方 视学算法 选择加 星标 或 置顶 重磅干货 第一时间送达 作者丨米阿罗 知乎 已授权 来源丨https zhuanlan zhihu com p 486360176 编辑丨极市平台 首发于踢翻炼丹炉 https www zhihu
  • UncaughtExceptionHandler 捕获异常线程以及出现异常重启

    1 捕获线程的异常只需要修改Executor产生线程的方式 即为每一个线程添加一个实现了Thread UncaughtExceptionHandler接口的异常处理器来捕获线程发生的异常 出现异常之后在捕捉异常中在重新开启线程即可 例子如下
  • Spark内存管理-UnifiedMemoryManager和StaticMemoryManager

    在Spark 1 6 0中 引入了一个新的参数spark memory userLegacyMode 默认值为false 表示不使用Spark 1 6 0之前的内存管理机制 而是使用1 6 0中引入的动态内存分配这一概念 从SparkEnv
  • Linux线程编程

    参考 Linux多线程编程初探 作者 峰子 仰望阳光 网址 https www cnblogs com xiehongfeng100 p 4620852 html 目录 线程概述 线程概念 线程与进程区别 为何用线程 线程开发api概要 线
  • 第三章内存管理

    1 内存的基础知识 内存可存放数据 程序执行前需要先放到内存中才能被CPU处理 缓和CPU与硬盘之间的速度矛盾 指令中的地址参数直接给出了变量x的实际存放地址 物理地址 1 绝对装入 绝对装入 在编译时 如果知道程序将放到内存中的哪个位置
  • 代码静态分析工具——splint的学习与使用

    引言 最近在项目中使用了静态程序分析工具PC Lint 体会到它在项目实施中带给开发人员的方便 PC Lint是一款针对C C 语言 windows平台的静态分析工具 FlexeLint是针对其他平台的PC Lint版本 由于PC Lint
  • linux 调试技术

    本文讨论了四种调试Linux程序的情况 在第1种情况中 我们使用了两个有内存分配问题的样本程序 使用MEMWATCH和 Yet AnotherMallocDebugger YAMD 工具来调试它们 在第2种情况中 我们使用了Linux中的s
  • C#学习笔记 任务操作

    利用线程 可以方便地进行异步操作 但是线程模型有一个缺点 就是无法处理返回值 要在不同线程之间传递数据比较麻烦 任务则解决了这个问题 完整代码在这里 https github com techstay csharp learning not
  • Qt内存管理(三) Qt的智能指针

    智能指针则可以在退出作用域时 不管是正常流程离开或是因异常离开 总调用delete来析构在堆上动态分配的对象 Qt常用的智能指针有QPointer QScopedPointer QSharedPointer 关于这几个智能指针 网上的博客基
  • CUDA编程中内存管理机制

    GPU设备端存储器的主要分类和特点 大小 全局 Global 和纹理 Texture 内存 大小受RAM大小的限制 本地 local 内存 每个线程限制在16KB
  • 内存管理方案

    内存管理方案 Memory Management System Author Owen 目 录 内存管理方案 1 目 录 1 1 概述 2 2 理论依据 2 2 1 不对内存进行管理 2 2 2 对内存进行内部管理 2 3 实现方案 2 3
  • 为什么栈的数组长度必须是一个常量?而堆的数组长度可以是变量。为什么栈的大小有限制?

    为什么栈的数组长度必须是一个常量 而堆的数组长度可以是变量 栈区数组长度使用变量会报错 其原因就在于栈是编译器管理的 在程序运行前就已经分配好了空间的大小 而使用变量 编译器无法知道该分配多大的内存空间 于是报错 但堆上的内存是动态创建的
  • SimpleDateFormat线程不安全及解决办法

    以前没有注意到SimpleDateFormat线程不安全的问题 写时间工具类 一般写成静态的成员变量 不知 此种写法的危险性 在此讨论一下SimpleDateFormat线程不安全问题 以及解决方法 为什么SimpleDateFormat不
  • Go内存管理及性能观测工具

    内存管理 TCMalloc Golang内存分配算法主要源自Google的TCMalloc算法 TCMalloc将内存分成三层最外层Thread Cache 中间层Central Cache 最里层Page Heap Thread Cach
  • Linux内核内存检测工具KASAN

    KASAN k z n KASAN 是 Kernel Address Sanitizer 的缩写 它是一个动态检测内存错误的工具 主要功能是检查内存越界访问和使用已释放的内存等问题 KASAN 集成在 Linux 内核中 随 Linux 内
  • Java线程的6种状态及切换(透彻讲解)

    Java中线程的状态分为6种 1 初始 NEW 新创建了一个线程对象 但还没有调用start 方法 2 运行 RUNNABLE Java线程中将就绪 ready 和运行中 running 两种状态笼统的称为 运行 线程对象创建后 其他线程
  • 55黑马QT笔记之关闭子线程

    55黑马QT笔记之关闭子线程 1 这里为什么要单独写多一篇文章来说线程的关闭呢 主要是想让大家提升印象 养成资源回收的好习惯 任何时候都要想起开辟过的内存回收 这里的关闭子线程上一篇也写到了 就是利用关闭窗口时调用槽函数回收掉 2 具体步骤

随机推荐

  • 【PTA】整除光棍

    一 题目 光棍 说的是全部由1组成的数字 比如1 11 111 1111等 传说任何一个光棍都能被一个不以5结尾的奇数整除 比如 111111就可以被13整除 现在 你的程序要读入一个整数x 这个整数一定是奇数并且不以5结尾 然后 经过计算
  • linux中/etc/inittab文件分析

    一 什么是init init是Linux系统操作中不可缺少的程序之一 是一个由内核启动的用户级进程 内核启动 已经被载入内存 开始运行 并已初始化所有的设备驱动程序和数据结构等 之后 就通过启动一个用户级程序init的方式来启动其他用户级的
  • Java中float、double、long类型变量赋值添加f、d、L尾缀问题

    1 添加尾缀说明 我们知道Java在变量赋值的时候 其中float double long数据类型变量 需要在赋值直接量后面分别添加f或F d或D l或L尾缀来说明 其中 long类型最好以大写L来添加尾缀 因为小写l容易和数字1混淆 例如
  • 三分钟了解APS系统中生产计划排程模块的基本原理

    版权声明 本文为CSDN博主 weixin 45414340 的原创文章 遵循CC 4 0 BY SA版权协议 转载请附上原文出处链接及本声明 原文链接 https blog csdn net weixin 45414340 article
  • 【吴恩达-AIGC/ChatGPT提示工程课程】第九章 - 总结

    吴恩达 AIGC ChatGPT提示工程课程 第九章 总结 恭喜你完成了这门短期课程 总的来说 在这门课程中 我们学习了关于prompt的两个关键原则 编写清晰具体的指令 如果适当的话 给模型一些思考时间 你还学习了迭代式prompt开发的
  • python实现简单爬虫和数据可视化-爬取豆瓣top250电影信息

    此内容全程跟着成都工业大学的李巍老师爬虫入门视频敲的代码 如有侵权删 观看的视频链接如下 李巍老师爬虫入门视频 整个爬虫可分为三个部分 1 爬取网页 https movie douban com top250 start 0 2 解析数据
  • feign超时时间设置_Spring Cloud 项目各种超时时间设置详解

    1 本文主要内容 服务之间调用Hystrix针对单个方法超时时间设置 Spring Cloud Gateway 针对单独URL的超时时间设置 2 超时时间设置场景 通常整个系统会有统一的接口超时时间设定 一般情况下的增删改查也都会比较快 但
  • 面试经验分享

    核心 几个大块的内容 前期准备 简历 自信 实力 态度 语言表达 1 简历制作 简历要有特点 将博客 GitHub 自己的作品链接 还有电子版本的简历链接直接写上去 很重要 特长描述 工作经历 岗位职责 技能描述 项目经历描述 每一个项目都
  • Altium Designer中的电路仿真

    今天看了下Altium Designer的电路仿真功能 发现它还是蛮强大的 按着help里面的文档 TU0106 Defining running Circuit Simulation analyses PDF 跑了一下 觉得还行 所以就把
  • 【满分】【华为OD机试真题2023 JAVA&JS】寻找符合要求的最长子串

    华为OD机试真题 2023年度机试题库全覆盖 刷题指南点这里 寻找符合要求的最长子串 知识点双指针 时间限制 1s 空间限制 256MB 限定语言 不限 题目描述 给定一个字符串 s 找出这样一个子串 1 该子串中的任意一个字符最多出现2次
  • Type-C协议简介(CC检测原理)

    Type C协议简介 CC检测原理 作者 AirCity 2019 12 15 Aircity007 sina com 本文所有权归作者Aircity所有 1 简介 越来越多的手机开始采用Type C作为充电和通信端口 Type C连接器实
  • mesa源码阅读笔记(7)_顶点变换流程解析

    mesa源码阅读笔记 7 顶点变换流程解析 好久没有写博客 同时也放下对mesa源码的阅读很久了 这一篇会是我最后的一篇 有不尽到之处也会放下了 毕竟OpenGL不是我的强项 后面可能没有这么多时间来关注了 这篇文章有点长 而我也不知道自己
  • 毕设-解决移动端用HTTP协议从onenet平台上获取数据流的多个数据点的问题

    onenet平台 OneNET是由中国移动打造的PaaS物联网开放平台 平台能够帮助开发者轻松实现设备接入与设备连接 快速完成产品开发部署 为智能硬件 智能家居产品提供完善的物联网解决方案 产品信息 至于怎么创建产品我就不做过多的介绍了 我
  • 最大公约数和最小公倍数(详解有实例)C语言

    最大公约数这里我运用了辗转相除法来实现 辗转相除法的意思是给出所要求的两个数之后 用大数取余小数 如果为0 那么那个小数就是最大公约数 如果不为1 我再用较大的数取余上个余数 依次循环 最后得到结果 给大家举个例子吧 12和16 首先用16
  • 云原生之使用minikube快速部署本地k8s集群

    云原生之使用minikube快速部署本地k8s集群 一 minikube 介绍 1 minikube简介 2 minikube特点 3 minikube的基本架构 二 本次实践介绍 1 本次实践目的 2 部署环境要求 3 本地环境规划 三
  • 视频流截取保存到本地路径(打包jar包CMD运行)

    需求 现在有一批https的监控视频流URL 需要以多线程模式监听视频流 对视频流进行每三秒截屏一次 将截取的图片post请求发送 根据响应判断图片是否保存到本地 保存时以当前时间命名 代码 BufferedImage类 import or
  • 匿名内部类在开发中的真实使用场景演示

    package Java project 1 import javax swing import java awt event ActionEvent import java awt event ActionListener public
  • linux开启使用ftp

    一 检查系统是否安装vsftpd rpm qa grep vsftpd 这里是安装好了 才会出现版本信息 没有安装不会出现 如果想删除卸载vsftpd使用 rpm qa grep vsftpd 查询出来版本好 通过 rpm e vsftpd
  • libuv使用总结

    libuv是单线程的 依靠uv run轮训当前线程关心的事件IO 所以这些函数的回调里尽量不要有阻塞的函数 否则回调之间相互影响 导致另外的回调走不到 libuv如果使用不当 会造成coredump 多线程用多线程的接口 单线程用单线程的接
  • jemalloc原理分析

    jemalloc原理分析 转载自http club alibabatech org article detail htm articleId 36 首先介绍一下jemalloc中的几个核心概念 1 arena jemalloc的核心分配管理