我发现搞懂 Go 语言内存对象分配,真的没有那么简单。为什么要搞懂 Go 语言的内存分配呢,吃饱了撑的呢!我计划多涉猎些博客,能弥补这块的知识缺失。但也可能中途就放弃了…

TCMalloc 图解

下图是截取自 《Go语言变编程入门和实战技巧》这本书中的示例图,Go 语言使用了类似这样的内存分配实现。TCMalloc 内存管理体系分为三个层次:ThreadCache、CentralCache、PageHeap。采用了三级的内存管理,分配内存和释放内存都从 ThreadCache 开始,向上逐级尝试。


内存管理的整体思路:首先在 ThreadCache 分配内存,如果内存分配失败,则从下一层的 CentralCache 中补一批上来,如果还不够就从 PageHeap 申请,再不够就向操作系统申请。释放内存也类似,逐级归还。

这里重点强调一下 ThreadCache 这个对象,很容易让人想到 Go 调度中 M 对象,M 扮演线程的角色。在 P 对象的结构体中包含一个 mcahce 对象,虽然 mcache 没有声明在 M 结构体中,但 mcache 对应的其实就是图中的 ThreadCache 对象。

再次强调一下 mcache 对象,下面是源码库中对 mcache 的注释,关注到三个细节点:小对象、单线程、无锁操作。让我们思路重新回到 TCMalloc 这张图上。

// Per-thread (in Go, per-P) cache for small objects.
// This includes a small object cache and local allocation stats.
// No locking needed because it is per-thread (per-P).
//
// mcaches are allocated from non-GC'd memory, so any heap pointers
// must be specially handled.
//

如果只是看上面那张图,感觉已经把该囊括的都囊括了,但又觉得只是蜻蜓点水。

我查看了 TCMalloc : Thread-Caching Malloc 中对于 TCMalloc 的介绍,和第一张图相比,这张图在介绍的时候,拆成了三个模块:front-end 负责快速分配、回收内存;middle-end 用于补充 front-end 所需内存;back-end 用来从操作系统申请内存。

但是,我们依旧能看到 Per-thread、Center free list、page heap 这几个重复的角色,两者相互佐证一下,TCMalloc 可能真的就是这样子。图中提到的 Legacy page heap,我比较奇怪,为什么要使用 Legacy 这个形容词呢?

关于这三层结构,我有话要说:确定模块的边界非常重要,不同的模块有明确的不同职责。这样的设计其实很常见,我们在设计缓存架构时,常见的三层查询:本地内存 -> Redis -> DB,本质上其实差不多。

小对象申请

下面计划深入一些细节,TCMalloc 设计了两种内存管理形式,分别是 span 和 object。其中,span 是由一组连续 page 组成的内存块,它由 central 进行管理;object 是将 span 按照特定规格进行切割,固定尺寸的小块内存。

之所以再特别强调一下 object,是因为别把这个 object 理解错了,在这篇文章里,它就描述固定尺寸的小块内存。

接下里,我要开始翻另一篇 TCMalloc : Thread-Caching Malloc 文章,关于小块内存的的申请。ThreadCache 主要负责小块内存的分配,根据需要申请的内存大小计算对应的 size class,然后从对应的 object 链表中获取 object。

如下面这张图所示,每个 size class 都对应了一个 object 链表。如果查找到的 object 链表非空,我们直接移除链表的头结点并返回。如果为空,就向 central free list 申请一批该尺寸的 的 object 加入到链表中,重新执行非空链表的获取逻辑。

关于提到的 object,该如何在代码中体现出来呢?每个 size class 对应一个 object 链表,类似于一个本地对象池。在这个池子为空的时候,可以申请向池子中添加 object。但是当池子满了的话,后续释放的 object 就无法放回池子,这部分 object 就需要被回收。池子的初始尺寸多大?该如何回收那行无法放回池子的 object?

正如上面提到的问题,通过阅读别人写的博客,是无法了解到具体细节的,主要还是看我们想了解到什么程度。

大对象申请

我们继续看大对象的申请,它和小对象的申请是明显区分的。针对超出 size class 范围的内存对象,会按照 page 为单位进行申请,如下图所示,它和小对象的 class size 类似,也是从小到大的等级链表。不过,这里的申请逻辑和小对象申请有明显的差异。

下图中不同数量的 page,其实表示的是不同尺寸的 span 对象。当所需尺寸的 span 没有空闲时,可以把更大尺寸的 span 进行拆分,如果大的 span也没有了,就需要向操作系统申请。

比如,我需要申请 3 pages 的内存,但是 3 pages 对应的链表为空,我会继续看 4 pages 是否有可用的内存,直到最终找到一个可用的等级内存。假设 4 pages 链表也为空,我最终匹配到了 5 pages 的内存。但我实际值需要 3 pages 的内容,那多出来的 2 pages 会被插入到合适的链表中。

因为申请到更大的尺寸,那多余出来的 pages,是如何分配插入其他合适链表的呢?这个也很重要,比如上面多出来的 2 pages,是插入到 2pages 对应的链表呢?还是拆分成 2 个独立的 page,插入到 1page 对应的链表?万一1 page 和 2 pages 链表中非空元素特别多怎么办?

我也不知道

Go参考TcMalloc内存分配相关推荐

  1. Tcmalloc内存分配算法的分析

    一.介绍 tcmalloc是Google搞的一个内存管理算法,据说分配速度要比glibc自带的malloc快很多.但是客观分析来说,只是在某些场景下是如此.tmalloc具有现代内存管理器的特点,可以 ...

  2. 利用TCMalloc替换Nginx和Redis默认glibc库的malloc内存分配

    TCMalloc的全称为Thread-Caching Malloc,是谷歌开发的开源工具google-perftools中的一个成员.与标准的glibc库的Malloc相比,TCMalloc库在内存分 ...

  3. tcmalloc jemalloc glibc内存分配管理模块性能测试对比

    tcmalloc是谷歌提供的内存分配管理模块 jemalloc是FreeBSD提供的内存分配管理模块 glibc是Linux提供的内存分配管理模块 并发16个线程,分配压测3次,每次压15分钟,可以看 ...

  4. ptmalloc,tcmalloc和jemalloc内存分配策略研究

    转载:https://cloud.tencent.com/developer/article/1173720 操作系统内存布局 各种malloc的内存分配管理方式离不开操作系统的内存布局策略. 32位 ...

  5. 一个可以参考的JVM内存分配

    下面是java命令有关JVM内存分配的参数 JAVA_MEM_OPTS="" BITS=`java -version 2>&1 | grep -i 64-bit` i ...

  6. Linux创建线程时 内存分配的那些事

    文章目录 问题描述 问题分析 针对问题1 的猜测: 针对问题2 的猜测: 原理追踪 总结 问题描述 事情开始于一段内存问题,通过gperf工具抓取进程运行过程中的内存占用情况. 分析结果时发现一个有趣 ...

  7. TCMalloc内存分配器如何减少内存碎片?

    目录 前言 什么是内存碎片? 内存碎片-Freelist 内存碎片-Segregated-Freelist 内存碎片-Buddy-System 内存分配算法的比较 TCMalloc的内存碎片 TCMa ...

  8. 图解tcmalloc内存分配器

    目录 前言 如何分配定长记录? 如何分配变长记录? 大的对象如何分配? Span如何分配? 从Page到Span PageHeap 全局对象分配 ThreadCache 总结 参考 推荐阅读 前言 T ...

  9. go-内存管理篇(二) 万字总结-golang内存分配篇

    前言 本文是讲解Golang内存管理的第二篇,在第一篇中我们提到,Golang的内存分配模式与TCMalloc是极其相似的. 所以先来回顾一下TCMalloc相关知识点. Page:TCMalloc也 ...

最新文章

  1. 自己动手实现简易代码生成器、采用文本模板文件生成服务层、服务层接口代码的做法参考...
  2. html 执行外部js的函数,javascript – Chrome扩展程序:加载并执行外部脚本
  3. php获取当天的日期-年月日与星期几
  4. GATT之Device information Service
  5. 智能路由器-OpenWRT 系列四 (挂载移动设备)
  6. 【渝粤教育】国家开放大学2019年春季 2205-22T开放英语2 参考试题
  7. c++用一级运算比较大小_16.初中数学:怎么比较a、b、c、d的大小?幂的运算,基础常见考题...
  8. java的HTML5常量用final说明
  9. 多线程的第三种模式(callable)
  10. foxmail提示不知道这样的主机_开车上八楼停车场,坡道拐弯会车要这样做,知道了不吃亏...
  11. 分步骤演示如何使用Filter链拦截MyServlet的同一个请求
  12. java 元组 getinteger_TS数据类型:从C++/Java/Python到TS看元组tuple—元组的来龙去脉...
  13. PCL Lesson1 :PCL库PCLVisualizer的简单使用
  14. 第二阶段冲刺报告(三)
  15. 设计模式——单例模式八种方式实现与分析(附代码示例)
  16. uni-app教程支付php,uni-app IOS app微支付、支付宝整合记录
  17. <el-descriptions>无法使用的问题
  18. c语言小球碰壁,小球碰壁效果
  19. 秋冬心血管疾病高发,牢记这几个身体异常症状!
  20. 曾被诉“抄袭”,头条搜索想要突围有点难

热门文章

  1. 红黑二叉树原理和分析
  2. 【愚公系列】2022年01月 Mysql数据库-Mysql介绍和安装
  3. Git服务器搭建及Gitolite权限管理
  4. Electron-vue dialog.messageBox 组件使用
  5. 中国工业气体运行现状与未来供需前景预测报告2022-2027年
  6. openlayers图层开关控件
  7. iPhone 4S 降至149美元 iPhone 5 即将到来?
  8. 分享一个樱花漫天飞舞的html效果
  9. 关于如何查询一个期刊是否被SCI或其他机构收录
  10. 2014-2015-2试题