内存分配器概述&对比ptmalloc和tcmalloc

关于内存分配器ptmalloc以及tcmalloc的详细讲解:

内存分配器------彻底理解tcmalloc

内存分配器------彻底理解ptmalloc


为什么要有内存管理

因为brk、sbrk、mmap都属于系统调用,若每次申请内存,都调用这三个,那么每次都会产生系统调用,影响性能;其次,这样申请的内存容易产生碎片,因为堆是从低地址到高地址,如果高地址的内存没有被释放,低地址的内存就很难被回收(当然,共享区没有这个限制)。因此内存管理其实有两个作用:

  • 优化性能
  • 缓解内存碎片问题(一方面是管理并复用brk产生的碎片,一方面解决内存池为了性能本身把内存分块管理造成的碎片问题)

内存管理概述

内存管理分为用户程序层、C 运行时库层、内核层三个层面,其中分配器 allocator 属于 C 运行时库的内存管理模块,它负责响应用户程序的内存分配请求,再向内核申请内存并返回给用户;为提升分配效率,allocator 通常会预先申请一块远超用户需求的内存自行管理,用户释放的内存也不会立即还给操作系统,而是由 allocator 统一维护空闲内存块,后续有新分配需求时会优先从空闲空间中匹配合适内存,匹配不到才再向内核申请新内存,业界主流的内存分配器有 glibc 默认标配的 ptmalloc、Google 的 tcmalloc 以及 Facebook 的 jemalloc。


ptmalloc与tcmalloc对比

  1. 线程并发处理
    • ptmalloc:通过将内存分为多个分配区(arena)来缓解多线程锁竞争,但分配区数量有限,且一个分配区可能被多个线程共享,因此在高并发下仍存在性能瓶颈。
    • tcmalloc:为每个线程分配一个 threadCache,实现无锁的内存申请和释放,大幅提升并发性能。
  2. 内存局部性优化
    • ptmalloc:使用 last remainder chunk 来提升局部性,效果不确定。
    • tcmalloc:每个线程几乎总是从同一个 Span 切割同大小内存块,自然具备更好的局部性,对连续小块内存分配更高效。
  3. 内存占用
    • ptmalloc:内存占用不是特别多,因为分配区是有限的。但是****长时间运行容易出现内存暴增,因为只有靠近 top chunk 的内存块被释放时才会触发缩容。
    • tcmalloc:内存占用很多,因为每个线程都要有一份ThreadCache以及其中的各种类型的内存块
  4. 小块内存合并
    • ptmalloc:合并小块内存时,总是需要向前向后遍历空闲块,操作相对较慢。
    • tcmalloc:小块内存合并非常快且自然,只需对应 Span 的计数器减减即可。
  5. 资源调度与忙闲不均
    • ptmalloc:无法合理处理线程使用不均的情况。例如,线程 A 频繁申请内存,线程 B 几乎不申请,B 却浪费了分配区资源。
    • tcmalloc:使用 centralCache 进行线程间的合理调度,避免资源浪费。 ​​​​​​​

总结

ptmalloc 适合通用、线程数不极端的环境,无明显偏好,兼容性最好。

tcmalloc 在多线程高并发、频繁分配/释放大量小对象的场景下优势显著(如果频繁),尤其适合对延迟敏感以及内存消耗不敏感的服务。

相关推荐
君鼎2 天前
内存池完整实现——C++20版
c++20·内存池
不吃土豆的马铃薯8 天前
5.SGI STL 二级空间配置器 _S_chunk_alloc核心函数解析
开发语言·c++·vscode·c·内存池
不吃土豆的马铃薯8 天前
4.SGI STL 二级空间配置器 allocate 与_S_refill 源码解析
c语言·开发语言·c++·dreamweaver·内存池
June`12 天前
高并发内存池如何实现
c++·tcmalloc·内存池
YYYing.12 天前
【C++项目之高并发内存池 (五)】一些小细节和性能优化及整体测试
c++·性能优化·高并发·内存池·基数树
YYYing.15 天前
【C++项目之高并发内存池 (四)】三层缓存的空间回收流程详解
c++·笔记·缓存·高并发·内存池
YYYing.18 天前
【C++项目之高并发内存池 (三)】万字解析CentralCache与PageCache的初步实现
c++·笔记·哈希算法·高并发·c/c++·内存池
YYYing.1 个月前
【C++项目之高并发内存池 (一)】项目介绍与定长内存池的构建
项目·c/c++·内存池·池化技术
洛水水1 个月前
图解式讲解内存池:告别内存碎片与随机coredump
linux·内存池