当前位置: 首页 > news >正文

TCMalloc原理解析(上)

在学习内存管理时,学习TCMalloc的原理肯定是值得的。对于TCMalloc如何加载使用,本章不作介绍,如今AI发展迅猛,加之也有很多使用说明相关的文章,完全上网参考,这里推荐:(8 条消息) TCMalloc解密(一) - 知乎。

这里参考的源码是:tcmalloc: TCMalloc (google-perftools) 是用于优化C++写的多线程应用,比glibc 2.3的malloc快。这个模块可以用来让MySQL在高并发下内存占用更加稳定。

  1. TCMalloc的简介

TCMalloc采用了“三级缓存”的架构(ThreadCache、CentralCache和PageHeap)、TLS和TSD机制,显著减少了锁竞争,提高了多线程环境下的内存分配效率,非常适用于并发场景。

1.1 TCMalloc的内存分配算法(简)

TCMalloc把内存按大小分成三类:

  • TCMalloc默认将page(页)的大小对齐为8KB(1 << 13)

  • 小内存对象:这段内存对象由三级缓存(ThreadCache、CentralCache和PageHeap)轮转管理,按括号里的前后顺序来分级分配。

    • 小内存对象(0,256KB]。

    • 中内存对象(256KB,1MB]。

  • 大内存对象(1MB,~]。这里的内存大于128page,由有序Set来管理。

ThreadCache即线程持有的本地缓存,在ThreadCache中存在FreeList类,用于管理从CentralCache中分配来的内存对象。

CentralCache中包含Span成员,Span内管理着从PageHeap中分配下来的连续的page对象,一个Span管理的对象(内存对象),大小至少为1个page或着n个page,这些连续的page就称为Span。其中由CentralCache这个类来管理分配的Span,向下给ThreadCache提供/回收内存对象的分配,向上向PageHeap申请/交还内存对象。

PageHeap,在TCMalloc中,由它来作为向OS申请内存的缓存,在它与OS中间又设计了一层缓存来提高分配效率,它就是整个三缓体系的内存来源---向下层的CentralCache提供/回收Span对象。它以Span为单位向OS进行内存申请,Span的大小为1到n个page。如下图↓

1.2 Size Class

在TCMalloc内存分配器中,size class是核心设计概念之一,TCMalloc按内存请求将大小划分为多个size class,每个size class对应一个范围的内存大小,如1~8B对应8B的size class,9~16B对应16B的size class。

TCMalloc为内存<=256KB)定义了约85~88个size class,这些size class按大小间隔递增。

  • 如8B、16B、24B、......、256KB,其中间隔大小也由内存尺寸变化而变化,小尺寸间隔8B,中尺寸间隔16B,大尺寸间隔32B,以此类推,最大间隔不超过256B

这样内部碎片率控制在12.5%以内,外部碎片通过页级分配器管理。

1.3 ThreadCache

ThreadCache负责为每个线程提供快速的本地缓存,每个线程都有独立的ThreadCache,在小对象的分配下,其时间复杂度接近O(1)。其中ThreadCache管理着FreeList数组,FreeList数组按size class划分了多个双向空闲链表,每个链表挂在对应大小的内存对象。

小对象的分配可以直接在FreeList上操作,回收的小对象也是优先挂到FreeList上。因为是线程自己持有的,所以不需要加锁。

为了方便统计数据,用双向链表将每个线程的ThreadCache管理了起来。这里使用这张图可以很好得来表示:

1.4 CentralCache

当ThreadCache中内存不足或者内存过多时,就需要向上一层的CentralCache申请或者归还。CentralCache作为全局共享的缓存层,它链接着ThreadCache以及PageHeap,起着桥梁作用,当ThreadCache中的内存用尽时,需要向CentralCache申请,这个过程时需要加锁的,CentralCache向PageHeap申请内存的时候,也是需要加锁的,当然在CentralCache中操作几乎都是要加锁的。

CentralCache中管理着CentralFreeList,与ThreadCache中的FreeList类似,它同样也是按size class来划分管理内存对象的,同样也是双向链表。同样借用知乎大佬的图:

Span是CentralCache中管理内存的基本单位,CentralCache用两个双向链表来管理从PageHeap中申请来的Span,每个Span会被切分为固定大小的内存块,以供ThreadCache使用。

1.5 PageHeap

PageHeap作为CentralCache和ThreadCache的后端核心,直接与操作系统交互,负责大内存(>256KB)的回收和分配,它为CentralCache提供Span,用以支持小对象的分配。

PageHeap采用了两种策略来管理Span。小Span(<=128page)使用链表进行管理,并根据Span的大小分桶管理,大Span(>128page)采用有序集合(如std::set)按大小排序。

  1. 内存分配

上面讲到内存划分,这里就到各类内存的分配流程,可能并不会那么细致,在后面的源码讲解部分会补充到。

2.1 内存对象分配

对于小中大内存对象的分配,在介绍ThreadCache、CentralCache以及PageHeap的时候已经将流程大致穿插进去,这里就作流程总结:

  1. 将要分配的内存向上取整对应到相应的size class。

  2. 到线程本地的ThreadCache中查找对应size class的FreeList链表

    1. 若查找到,则分配第一个空闲对象给线程,结束。

    2. 若没有,转到3。

  3. 到CentralCache对应size class的FreeList中查找。

    1. 获取相应的桶锁。

    2. 若其中有空闲的内存对象,返回第一个空闲的内存对象,分配结束。

    3. 若没有,转到4。

  4. 将size class对齐到整数个page,获取PageHeap的锁,向PageHeap申请Span,PageHeap优先从缓存的小Span链表中查找满足需求的Span。

    1. 若找到,返回Span,或分割更大的Span,将分割剩余的Span链入更小的Span链表,分配结束。

    2. 上面算是小中内存的分配~~~当上面的流程申请失败,就是去申请大内存对象(>128page---1MB)~~~~~~~~~~~~~~以下就是大内存的分配了

    3. 若Span链表中未找到,到大Span集合中根据“最佳匹配”算法查找,若找到则分割Span并返回,将剩余的Span链入Span链表或放入大Span集合中,分配结束。若未找到,转到5。

  5. PageHeap向系统申请Span,调用sbrk或mmap去申请内存,再用Span管理,然后分割,将需要的n页Span返回给CentralCache,将剩余的Span放到小Span链表或大Span集合中(分割后仍然大于128page)。分配结束。

这就是大致的流程了。

http://www.dtcms.com/a/498910.html

相关文章:

  • OpenCV深度学习:目标检测、人脸识别与智能视频分
  • 电子商务网站有哪些内容wordpress漏洞2019
  • FileNotFoundError: [WinError 3] 系统找不到指定的路径。
  • qq音乐怎么做mp3下载网站安阳县教育局官网
  • 深度学习进阶(七)——智能体的进化:从 LLM 到 AutoGPT 与 OpenDevin
  • Redis面试八股
  • 做网站从设计到上线流程山西专业网站建设价目
  • 排序算法:详解插入排序
  • [MLflow] 部署OpenAI聊天网关 | 令牌桶算法限流 | 分布式追踪 | Trace Span
  • 【010】智能图书系统
  • LeetCode 刷题【124. 二叉树中的最大路径和】
  • linux 的文件结构
  • stack,queue,咕咕咕!
  • 做网站不实名认证可以吗佛山城市建设工程有限公司
  • 构建基于大语言模型的智能数据可视化分析工具的学习总结
  • Android 架构演进全解析:MVC、MVP、MVVM、MVI 图文详解
  • 网站后台免费模板下载艺术字体在线生成器转换器
  • HC32 操作GPIO点亮LED(HC库)
  • 如何用python来做小游戏
  • 捡到h3开发板,做了个视频小车(二),御游追风plus做遥控器
  • U盘安装群晖RR引导
  • 昆山市住房和城乡建设网站wordpress淘宝联盟
  • 数据库中表和视图的关系
  • 优先级队列的学习(二)
  • 内部排序——一文速通
  • 数据结构——东方财富掘金量化速成学习(python)
  • 做网站商城项目的流程深圳专业网站设计哪家好
  • 【招聘】-音视频行业企业的招聘分析
  • css word属性
  • 晋中网站seo芯火信息做网站怎么样