TCMalloc


内存分配的重要因素: 速度

不同 malloc 分配速度对比:

malloc耗时减少锁争用空间效率
ptmalloc2300 ns线程 arena每个对象 4Bytes 头,大小四舍五入为 8 的倍数
TCMalloc50 ns1. 小对象几乎没有争用
2. 大对象使用细粒度和高效的自旋锁
1% 空间开销

注: ptmalloc2 不能从一个 arena 移到另一个 arena

问题

  • 为什么 TCMalloc 比 ptmalloc2 分配的速度快?

简介

TCMalloc 为每个线程分配线程本地缓存。

小对象:

TCMalloc 中 <= 32K 为小对象。

  • 小对象从Thread-local cache分配
  • 分配时对象从Central移到Thread-local cache
  • gc 周期性的将对象从Thread-local cache移回Central

大对象:

  • 大对象使用页级分配器从 Central 分配
  • 页按 4K 对齐

页可被划分为一系列大小相等的小对象。例如:1页(4K)可分为 32 个 128 Bytes 的对象。

在这里插入图片描述

小对象分配

划分

  • 按尺寸被映射为 170 个级别
  • 尺寸按 8 bytes 分隔,较大的按 16 Bytes,再大些的按 32 Bytes,以此类推。最大间距为 256 Bytes(size >= 2K)

管理

  • Thread Cache 包含每种尺寸级别的单链表

分配

  • 根据分配的大小找到相应的尺寸级别
  • 查看 Thread Cache 中相应的空闲列表
  • 如果 Thread Cache 空闲列表非空
    • 移除第 1 个对象并返回
  • 如果 Thread Cache 空闲列表为空,查 Central 空闲列表
    • 如果 Central 空闲列表非空
      • 从 Central 空闲列表获取一堆该大小的对象(所有线程共享 Central)
      • 将这些对象放到 Thread Cache 空闲列表
      • 返回 1 个对象给程序
    • 如果 Central 空闲列表为空
      • Central 的页级分配器分配一系列页
      • 将这一系列页分为该尺寸的对象
      • 将新对象放到 Central 空闲列表中
      • 将一些对象放到 Thread Cache 空闲列表

优点:这种方式分配 TCMalloc 不需要加锁。

在这里插入图片描述

大对象分配

划分

超过 32K 的对象由 central page heap 管理,central page heap 是一个由 1~255 page + rest page 组成的空闲链表。

分配

  • 如果分配 K页大小就找第 K 个空闲链表
  • 如果该空闲列表为空就依次查找,直到最后一个
    • 如果仍然为空,通过 sbrk,mmap 等方式从系统分配
  • 如果 K页足够满足分配需求,将剩余的放回到相应的空闲列表中

在这里插入图片描述

Span

TCMalloc 所管理的heap是由 page组成,而page又是由Span对象组成。

Span 有两种状态已分配空闲

  • 如果空闲,则在 page heap 空闲链表上
  • 如果已分配,则被大小对象处理,尺寸记录在 span 中

span 属于哪个 page 可以通过 central 数组的页码索引找到。例如:span a 占 2 pages, span b 占 1 page, span c 占 5 pages,span d 占 3 pages.

在这里插入图片描述

32 bit 地址空间可以容纳 2^20 个 4K 页面,共 4MB 空间。

释放

当一个对象要被释放时,我们计算页码并在 central 找到相应的 span 对象。

  • 如果是小对象,则插入到 Thread Cache 的相应空闲列表中。
    • 如果 Thread Cache 的空闲列表超过预定大小(默认 2M)则使用 gc 将对象移回 Central 的空闲列表中。
  • 如果是大对象,判断对象的 page 覆盖范围,假设是 [p, q],还需查找 p-1 和 q+1,如果临近的 span 也是空闲的,则进行合并,然后插入到 page heap 相应的空闲列表中。

Central 空闲列表基本由两部分组成:

  • 一组 span
  • 每个 span 的空闲对象列表
class CentralFreeList {
 private:
  struct TCEntry {
    void *head;  // Head of chain of objects.
    void *tail;  // Tail of chain of objects.
  };

  Span     empty_;
  TCEntry tc_slots_[kMaxNumTransferEntries];
};

参考

TCMalloc : Thread-Caching Malloc

https://github.com/gperftools/gperftools

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
TCMalloc是一个由Google开发的内存管理器,被广泛用于大规模的分布式系统中。它为多线程环境下的内存分和释放提供了高效的性能。 TCMalloc的实现主要包含以下几个关键特性: 1. Thread-Caching TCMalloc使用了线程本地缓存(Thread-Caching)的机制,每个线程都维护了一个本地缓存,用于快速分配和释放内存。这样可以避免不同线程之间频繁访问共享数据结构的开销,提高了内存分配和释放的性能。 2. Central Cache TCMalloc还维护了一个全局的中央缓存(Central Cache),用于存储较大的内存块。当本地缓存不足以满足内存需求时,线程会向中央缓存申请内存。 3. Page Heap TCMalloc使用了Page Heap来管理内存。Page Heap将内存按页进行划分,并使用位图来跟踪每个页的使用情况。这样可以提高内存分配和释放的效率,并减少内存碎片化。 4. Size Class TCMalloc将需要分配的内存按照大小进行分类,每个大小类都有一个对应的内存池。这样可以提高内存分配和释放的效率,并减少内存碎片化。 5. 高效的内存分配和释放算法 TCMalloc使用了一些高效的算法来管理内存,如位图、堆栈缓存等。这些算法能够快速地分配和释放内存,并且减少内存碎片化。 总的来说,TCMalloc通过使用线程本地缓存、中央缓存、Page Heap以及高效的内存分配和释放算法,实现了高性能的内存管理。它在Google的大规模分布式系统中得到了广泛应用,并取得了很好的效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值