美文网首页
全局内存分配器tcmalloc与jemalloc原理解析

全局内存分配器tcmalloc与jemalloc原理解析

作者: 谭英智 | 来源:发表于2023-02-02 17:14 被阅读0次

动机

c++的分配器malloc和free,在功能上保证内存分配的正确性

然而在性能上,却有明显的缺陷

  • 过多的系统调用
  • 频繁申请和释放内存
  • 内存碎片导致性能恶化

为了解决上面的问题,提出了很多内存分配的第三方库

其中比较出色的有tcmalloc和jemalloc

使用了它们,mysql的性能提高了30%

其中jemalloc具有更好的内存碎片管理,使得在内存局部性得到更大的发挥

tcmalloc介绍

tcmalloc全名Thread-Caching Malloc

表示以线程cache来维护内存分配

这样做可以减少锁或者原子变量的竞争

使得可以快速的申请和释放内存

Overview

malloc-tcmalloc-overview
  • Front-end是一个内存池,为了给应用快速的申请和释放内存的
  • Middle-end是用来整理内存的,它使用原子锁,来保证线程安全,并给Front-end提供内存和回收内存
  • Back-end是面向OS申请和释放内存的

Front-end

tcmalloc的Front-end是给应用快速申请和释放内存的

它的模式可以是per-thread cache或者per-cpu cache

per-thread是传统模式,为每个线程都分配一个独立的cache

per-cpu是新模式,为每个cpu核分配一个独立的cache,线程获取内存时,先查看自己在哪个cpu核运行,再去对应的cpu-cache中申请核释放内存,它通过Restartable Sequences技术来实现线程切换后可以无锁的获取内存

small和large对象申请

small内存,tcmalloc通过slab数据结构维护,应用可以在O(1)的时间获取和释放内存

large内存,需要直接到back-end申请

伙伴系统

malloc-tcmalloc-slab

对于小于kMaxSize的对象,划分成以大小为单位的类别,每个类别的内存块使用链表连接

当需要申请k大小的内存时,在分类中找最相近大小的类,并获取链表中的内存块,并返回

Front-end cache的大小

cache的大小如果超过阈值,那么释放的内存会回收到Middle-End

cache的大小如果小于阈值,那么将向Middle-End申请一片内存

Middle-End

通过锁来保证middle-end的线程安全

Transfer cache

Transfer cache通过维护一个slab cache,提供给Front-end快速的申请和示范内存

Central Free List

以span为单位来维护内存

一个span一般由多个page组成

transfer的cache块是通过分裂span来建成的

cache块的meta data会记录span id,来标记它来自哪个span

span通过bitmap数据结果,来判定span内部哪些区域被分配出去,哪些部分已经回收到span

Pagemap

malloc-tcmalloc-pagemap

使用2-level或者3-level的radix tree来管理span

key是span的id

每个span下面管理着若干个page

Page size

tcmalloc对应的page size可以是4k、8k、32k和256k

小page更容易管理cache块,可以更快速的归还给OS,申请小page的overhead更小

大page更少的系统调用,tree会更小

Back-end

面向OS,向OS申请大块的内存和释放整块的内存

malloc-tcmalloc-back

jemalloc介绍

jemalloc的设计跟tcmalloc是雷同的

所以这里只讲它跟tcmalloc在设计上做了哪些优化

arenas

jemalloc也是有per-thread cache

跟tcmalloc不一样的是

middle-end tcmalloc是全局只有一个

而jemalloc有多个组成,它们叫arenas

每个线程初始的时候绑定其中一个arena

多个arenas可以带来更小的全局锁竞争

slab数据结构的优化

tcmalloc的slab结构是以链表来维护的

它忽略了内存地址的因素

因此对于连续的申请内存,获取到的内存地址会十分随机

随着应用运行时间越长,会导致内部碎片越来越严重

应用的性能也会越来越差

jemalloc通过slab+rb-tree来维护内存块

每次提供给应用的内存块都是以最小内存地址的内存

这样,连续申请的内存,它们就会比较相邻

使得内存碎片得到缓和

相关文章

网友评论

      本文标题:全局内存分配器tcmalloc与jemalloc原理解析

      本文链接:https://www.haomeiwen.com/subject/cxqghdtx.html