前言
对于ptmalloc,tcmalloc,jemalloc网上有很多解析,讲的很好也很仔细,但是想要彻底看懂还是很有难度的,我这篇文章主要以自己的理解并结合形象的举例对比三者的区别,相对于大部分文章我不会深入的探讨三者的具体结构,而是从接触新手的角度,通过对比三者的区别,以举例子让大家对这三个常见内存池有一个整体且直观的概念,其中有很多地方舍弃了结构设计的细节,只保留核心的申请释放过程,讲解相对来讲没有那么严谨,如有错误请在评论区指正。
一、内存池
1)池化技术
池化技术是指将一类资源统一管理并重复利用,以减少资源分配和释放的频率,从而提升效率并降低系统开销。在内存管理中,池化技术主要用于小对象的内存分配,通过预先分配一块较大的内存区域,将其划分为多个固定大小的小块以满足频繁的内存请求。池化技术的核心思想是“重用”,尤其在那些内存分配和释放非常频繁的应用中,这种技术能够显著提高性能。
池化技术就像餐馆里的自助餐盘回收机制。想象一个高峰时段的餐馆,如果每次客人用餐后都需要餐馆去购买新的餐盘,显然效率会非常低,还会浪费资源。为了避免这种情况,餐馆会准备一批固定数量的餐盘,当客人用完后,服务员会清洗并重新放回取餐区域供下一个客人使用。这种重复利用餐盘的方式,不仅节省了资源,还让整个用餐流程更加高效。
在内存管理中,池化技术就像这些餐盘:系统预先准备了一批内存块,程序用完后会将它们归还,供后续的内存请求使用,从而避免频繁向操作系统申请和释放内存所带来的开销与混乱。
池化的优点包括:
- 减少分配开销:减少调用操作系统的内存分配接口(如
malloc或new)的次数。 - 提升性能:固定大小的内存块分配更快,同时避免碎片化问题。
- 降低内存碎片:通过统一管理,池化技术更容易控制和优化内存布局。
典型应用场景包括网络编程中的连接池、线程池,以及游戏开发中的对象池等。
2)内存池
内存池是一种基于池化技术实现的内存管理机制,它通过预分配一块内存区域,并对其进行统一管理,为小对象的内存分配提供支持。内存池通常会按照特定规则将内存分为多个固定大小的块(或称为“单元”),并在需要时将这些块分配给用户,释放时再归还到内存池中以供后续使用。
内存池的核心在于复用已分配的内存块,而不是频繁向操作系统请求和释放内存。这样可以显著降低系统调用的开销,同时避免因频繁分配和释放而导致的内存碎片问题。
1. 内存池的基本原理与目标
-
预分配内存
- 内存池在初始化时一次性向操作系统申请一大块连续的内存区域。
- 这块区域被划分为若干个大小一致的内存块,以支持频繁的小对象分配需求。
-
内存管理策略
-
空闲链表:内存池会维护一个空闲链表,用于记录所有未被分配的内存块。当有新的分配请求时,从链表中取出一个空闲块并返回;释放时再将其归还到链表中。
-
分区分配:有些内存池实现会根据块大小将内存池划分为不同的区域,以适配不同大小的对象分配需求。
-
-
减少系统调用
- 通过复用内存块,内存池可以减少对操作系统的内存分配和释放调用(如
malloc和free),降低了系统调用带来的开销。
- 通过复用内存块,内存池可以减少对操作系统的内存分配和释放调用(如
-
目标
-
提升效率:提供更快的内存分配和释放速度。
-
减少碎片:通过固定大小块的分配,避免内存碎片问题。
-
优化资源利用率:内存池可以帮助应用程序在高并发场景中高效管理内存,减少内存不足的问题。
-
2. 内存池设计考虑
为了实现一个高效的内存池,在设计中需要考虑以下关键因素:
-
分配效率:如何快速找到一个可用的内存块?是否需要支持多线程并发分配?
-
内存利用率:设计合理的块大小,以避免因分配过多大块内存而浪费资源。
-
线程安全:是否需要对内存池进行线程同步,或者采用线程本地池来减少锁争用?
-
可扩展性:如果内存池的预分配区域不够,是否支持动态扩展?如何回收不再使用的内存块?
-
内存对齐:确保分配的内存满足平台对齐要求,避免因未对齐导致的性能问题或错误。
-
内存生命周期管理:如何确保分配的内存块在释放时被正确归还?是否需要垃圾回收机制?
-
定位错误:为了调试方便,内存池应提供检测非法访问或重复释放的机制。
-
跨平台支持:内存池的实现应尽可能适配多种操作系统和硬件架构。
-
内存监控:提供内存池的使用统计(如分配次数、空闲块数量)以方便调试和优化。
二、ptmalloc
1)介绍
20 世纪 90 年代,随着多核处理器和多线程编程模型的普及,传统的内存分配器(如 dlmalloc)因其单线程设计,在并发场景中表现不佳,特别是在多线程程序频繁调用 malloc 和 free 时,容易导致锁争用,进而成为性能瓶颈。
为了应对这一问题,ptmalloc(pthread malloc)应运而生。它在 dlmalloc 的基础上进行了优化,通过引入线程局部内存管理策略,减少了全局锁的竞争,从而提升了多线程环境下的内存分配效率。
具体来讲,ptmalloc 是由 Wolfgang Gloger 在 1997 年开发的基于 dlmalloc(Doug Lea Malloc)的改进版本,专为解决多线程环境中的内存分配问题。随着多线程和多核处理器的普及,传统的单线程内存分配器(如 dlmalloc)在并发场景下效率较低,尤其在频繁调用 malloc 和 free 时容易发生锁争用,影响性能。ptmalloc 基于 dlmalloc,通过引入多线程支持的 arena 机制,显著优化了并发环境中的内存分配效率。
可以把 ptmalloc 的改进形象地看成一个大型自助餐厅的服务流程优化:
在传统的餐厅(类似于 dlmalloc)中,每次客人(线程)需要用餐时,都必须到服务台排队领取食物(获取内存)(类似于调用
malloc)。如果餐厅很忙,所有客人都集中到一个服务台,就会造成拥堵(即锁争用),影响用餐效率。而在改进后的餐厅(类似于 ptmalloc)中,餐厅经理(ptmalloc 的设计者)决定把食物分散到不同的区域,每个区域都有一套独立的自助食物领取站(arena)。每位客人按照就近的规则到自主食物领取站获取食物,不需要再排队到服务台,只有在一个领取站食物完全消耗,才会需要经理协调重新补充(对应极少的全局锁操作)。
这种改进的好处是:
- 每个区域的服务都是独立的(即一个arena有一把锁,如果不向同一个arena索要内存就不会加锁),不会互相干扰。
- 减少了集中管理带来的排队和等待(全局锁争用),提升了整体效率。
- 适合高峰期使用(多线程高并发场景)。
通过这种优化,ptmalloc 在多线程环境下的内存分配性能得到了显著提升,就像改进后的餐厅能更高效地服务客人一样。
2)ptmalloc解析
1. 核心概念
了解ptmalloc前我们要明白两个核心概念:
-
Arena(分配区):每个线程会优先使用自己的分配区,减少与其他线程的锁竞争。如果没有可用的分配区,系统会动态创建新的分配区。
-
Chunk(内存块):指内存池中分配的最小单位,每次内存申请都会从Arena分配区中切割出适合大小的内存块返回给用户。对于超大内存申请,直接调用操作系统的
mmap接口分配内存。
2. 线程与分配器的关系
ptmalloc 通过 动态创建多个 arena 来应对多线程的内存分

最低0.47元/天 解锁文章
2003

被折叠的 条评论
为什么被折叠?



