Linux内存管理(五):PTmalloc、TCmalloc、Jemalloc比较

1. 内存管理目标

2. 三种内存管理的比较


1. 内存管理目标

    内存管理的目的是实现了malloc(),free()以及一组其它的函数,以提供动态内存管理的支持。分 配器处在用户程序和内核之间,它响应用户的分配请求,向操作系统申请内存,然后将其返回给用户程序。

    为了保持高效的分配,分配器一般都会预先分配一块大于用户请求的内存, 并通过某种算法管理这块内存。来满足用户的内存分配要求,用户释放掉的内存也并不是立即就返回给操作系统,相反,分配器会管理这些被释放掉的空闲空间,以应对用户以后的内 存分配要求。也就是说,分配器不但要管理已分配的内存块,还需要管理空闲的内存块,当 响应用户分配要求时,分配器会首先在空闲空间中寻找一块合适的内存给用户,在空闲空间 中找不到的情况下才分配一块新的内存。

    由此可见,内存管理的核心目标主要有两点:

  • 高效的内存分配和回收,提升单线程或者多线程场景下的性能;
  • 减少内存碎片,包括内部碎片和外部碎片,提高内存的有效利用率;

2. 三种内存管理的比较

    ptmalloc 是基于 glibc 实现的内存分配器,它是一个标准实现,所以兼容性较好。pt 表示 per thread 的意思。当然 ptmalloc 确实在多线程的性能优化上下了很多功夫。由于过于考虑性能问题,多线程之间内存无法实现共享,只能每个线程都独立使用各自的内存,所以在内存开销上是有很大浪费的。

    tcmalloc 出身于 Google,全称是 thread-caching malloc,所以 tcmalloc 最大的特点是带有线程缓存,tcmalloc 非常出名,目前在 Chrome、Safari 等知名产品中都有所应有。tcmalloc 为每个线程分配了一个局部缓存,对于小对象的分配,可以直接由线程局部缓存来完成,对于大对象的分配场景,tcmalloc 尝试采用自旋锁来减少多线程的锁竞争问题。

    jemalloc 借鉴了 tcmalloc 优秀的设计思路,所以在架构设计方面两者有很多相似之处,同样都包含 thread cache 的特性。但是 jemalloc 在设计上比 ptmalloc 和 tcmalloc 都要复杂,jemalloc 将内存分配粒度划分为 Small、Large二个分类,并记录了很多 meta 数据,所以在空间占用上要略多于 tcmalloc,不过在大内存分配的场景,jemalloc 的内存碎片要少于 tcmalloc。

PTmallocTCmallocJemalloc
内存组织

(1)内存分配单位为chunk;

(2)小于64B的chunk放在fast bin中;

(3)64 - 512B放在small bin中;

(4)512B - 128 KB放large bin中;

(5)大于128KB不进行缓存;

(6)合并后的chunk放在unsorted bin中;

(1)内存有三层缓存:PageHeap、CentralCache和ThreadCache;

(2)0 - 256KB小对象放在中央缓存和线程缓存中,分为84个不同大小类别,中央缓存多个线程共享,线程级缓存每个线程私有;

(3)256KB - 1MB的中对象和1MB以上大对象放在PageHeap,每个page大小为8KB;

(1)小类区间为[8B, 14kb],共232个小类,每个类的大小并不都是2的次幂;

(2)大类区间为[16kB, 7EiB],page大小为4KB,从4 * page开始;

(3)内存分配单位为extent,每个extent大小为N * 4KB,一个 extent 可以用来分配一次 large_class 的内存申请,但可以用来分配多次 small_class 的内存申请。

分配流程fast bin —> small bins —> unsorted bin —> large bin —> top chunk —> 增加top chunk(sbrk/mmap) 或者 mmaped chunk;

(1)小对象:ThreadCache —> CentralCache —> PageHeap —> 内核;

(2)中对象和大对象:PageHeap —> 内核;

(1)小内存:cache_bin -> slab -> slabs_nonfull -> extents_dirty -> extents_muzzy -> extents_retained -> 内核

(2)大内存:extents_dirty -> extents_muzzy -> extents_retained -> 内核

多线程支持  没有线程级缓存,每个线程进行内存分配和释放时,需要对分配区进行加锁  每个线程拥有线程级缓存,当进行小对象分配和释放时,不用加锁处理  每个线程拥有线程级缓存tcache,进行小内存分配和释放时,不用加锁
优点它是一个标准实现,所以兼容性较好

(1)在多线程场景下,小对象内存申请和释放是无锁的,效率很高,中对象和大对象申请使用自旋锁;

(2)ThreadCache会阶段性的回收内存到CentralCache里,解决了ptmalloc2中分配区之间不能迁移的问题;

(3)占用更少的额外空间。例如,分配N个8字节对象可能要使用大约8N * 1.01字节的空间,即,多用百分之一的空间;

(1)采用多个arena来避免线程同步,多线程的分配是无锁的;

(2)细粒度的锁,比如每一个bin以及每一个extents都有自己的锁,并发度更高;

(3)使用了低地址优先的策略,来降低内存碎片化;

缺点

(1)管理长周期内存时,会导致内存爆增,因为与top chunk 相邻的 chunk 不能释放,top chunk 以下的 chunk 都无法释放;

(2)内存不能从一个分配区移动到另一个分配区, 就是说如果多线程使用内存不均衡,容易导致内存的浪费;

(3)如果线程数量过多时,内存分配和释放时加锁的代价上升,导致效率低下;

(4)每个chunk需要8B的额外空间,空间浪费大

  (1)对齐操作比PTmalloc多浪费一些内存,有点空间换时间;

(2)如果多个线程频繁分配大对象,对自旋锁的竞争会很激烈;

(1)arena之间的内存不可见,导致两个arena的内存出现大量交叉从而无法合并;

(2)大概需要2%的额外开销,tcmalloc是1%;

适用场景  不适合多线程场景和需要申请长周期内存,只适合线程数较少和申请短周期内存的场景适合多线程的场景适合多线程的场景,多线程并发度更好

性能对比图如下:

  • 5
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本文通过Glibc的内存暴增问题,主要介绍了系统的内存管理问题,具体如下: 目录 1. 问题 2. 基础知识 2.1 X86平台Linux进程内存布局 2.1.1 32位模式下进程内存经典布局 2.1.2 32位模式下进程默认内存布局 2.1.3 64位模式下进程内存布局 2.2 操作系统内存分配的相关函数 2.2.1 Heap操作相关函数 2.2.2 Mmap映射区域操作相关函数 3. 概述 3.1 内存管理一般性描述 3.1.1 内存管理的方法 3.1.2 内存管理器的设计目标 3.1.3 常见C内存管理程序 3.2 Ptmalloc内存管理概述 3.2.1 简介 3.2.2 内存管理的设计假设 3.2.3 内存管理数据结构概述 3.2.4 内存分配概述 3.2.5 内存回收概述 3.2.6 配置选项概述 3.2.7 使用注意事项 4. 问题分析及解决 5. 源代码分析 5.1 边界标记法 5.2 分箱式内存管理 5.2.1 Small bins 5.2.2 Large bins 5.2.3 Unsorted bin 5.2.4 Fast bins 5.3 核心结构体分析 5.3.1 malloc_state 5.3.2 Malloc_par 5.3.3 分配区的初始化 5.4 配置选项 5.5 Ptmalloc的初始化 5.5.1 Ptmalloc未初始化时分配/释放内存 5.5.2 ptmalloc_init()函数 5.5.3 ptmalloc_lock_all(),ptmalloc_unlock_all(),ptmalloc_unlock_all2() 5.6 多分配区支持 5.6.1 Heap_info 5.6.2 获取分配区 5.6.3 Arena_get2() 5.6.4 _int_new_arena() 5.6.5 New_heap() 5.6.6 get_free_list()和reused_arena() 5.6.7 grow_heap(),shrink_heap(),delete_heap(),heap_trim() 5.7 内存分配malloc 5.7.1 public_mALLOc() 5.7.2 _int_malloc() 5.8 内存释放free 5.8.1 Public_fREe() 5.8.2 _int_free() 5.8.3 sYSTRIm()和munmap_chunk(
### 回答1: glibc是GNU计划的一部分,是一套C语言标准库。内存管理是其中的一个重要组件。而ptmalloc2是glibc内存管理的一种算法,用于分配和释放内存块。 要下载glibc内存管理ptmalloc2源代码,可以通过以下几个步骤进行: 1. 打开GNU官方网站,找到glibc的相关页面,通常在https://www.gnu.org/software/libc/ 。 2. 在该页面上,找到下载链接或源代码仓库地址,这个地址通常会提供给用户下载最新版本的glibc。 3. 点击下载链接或者复制源代码仓库地址,将其粘贴到浏览器地址栏中。 4. 打开该链接后,您将能够下载一个压缩文件(通常是tar.gz或tar.bz2格式),包含了glibc的全部源代码。 5. 下载完毕后,解压压缩文件。您可以使用解压软件,如WinRAR或7-Zip。解压缩后,您将获得一个包含许多目录和文件的文件夹。 6. 在解压后的文件夹中,找到与ptmalloc2相关的源代码文件。通常这些文件会位于glibc源代码的malloc目录下。 7. 在malloc目录中,您将能够找到ptmalloc2源代码文件,这些文件名通常以"ptmalloc"或"ptmalloc2"开头。 以上是下载glibc内存管理ptmalloc2源代码的一个大致过程。通过该源代码,您可以深入了解ptmalloc2算法是如何在glibc中实现内存分配和释放的。但是请注意,阅读和理解源代码需要一定的计算机编程经验和相关背景知识。 ### 回答2: glibc是Linux操作系统中非常重要的一个C标准库,ptmalloc2是glibc中负责内存管理的模块之一。该模块负责动态分配和释放内存,并提供了多种内存分配器算法。 ptmalloc2源代码分析是深入研究该模块源代码的过程。通过分析ptmalloc2源代码,可以了解到它的实现原理、内存分配算法以及性能优化等方面的细节。 在下载ptmalloc2源代码之后,我们可以通过阅读和分析源代码来了解其内部结构和工作原理。在源代码中,我们可以找到一些关键的数据结构和函数,如malloc、free、realloc等。这些函数实现了动态内存分配和释放的基本功能。 通过阅读源代码,我们可以学习到ptmalloc2内存管理器的特点和优势。例如,ptmalloc2采用了分离的空闲链表来管理不同大小的内存块,利用了空闲块合并和分割等技术来提高内存的利用率和性能。此外,源代码还可能包含一些与内存操作相关的底层函数和宏定义。 分析ptmalloc2源代码不仅可以帮助我们理解其内部实现,还可以为我们定位和解决内存管理相关的问题提供指导。如果遇到性能问题或者内存泄漏等现象,我们可以通过分析源代码来找到问题的根源,并提出相应的优化措施。 总之,通过对glibc内存管理模块ptmalloc2的源代码进行分析,我们可以深入了解其实现原理和内部机制,为我们在实际项目中正确、高效地使用内存管理功能提供帮助。 ### 回答3: glibc是Linux系统上使用最广泛的C语言函数库,而ptmalloc2则是glibc中负责内存分配和管理的部分源代码。 首先,需要明确的是,glibc的ptmalloc2源代码并不是一个独立的项目,而是glibc库中的一部分。如果需要下载该源代码,可以通过访问glibc的官方网站或者使用git等工具来获取。 分析glibc内存管理ptmalloc2源代码可以帮助开发者更好地理解和使用glibc的内存分配功能。ptmalloc2实现了一种基于堆的内存分配算法,它采用了多种策略来管理内存,如bin和fastbin等。源代码的分析可以帮助我们了解这些策略的具体实现细节,以及它们在不同场景下的行为。 要对ptmalloc2源代码进行分析,可以首先阅读相关文档,如glibc的官方文档或论文。 掌握ptmalloc2的整体架构、数据结构和算法等基本知识后,可以通过逐行或逐函数地阅读源代码来深入理解其内部工作机制。可以关注一些关键函数的实现,如malloc、free、realloc等,以及相关的数据结构和算法。 此外,还可以参考开源社区中对ptmalloc2源代码的分析和解读,如一些博客文章、论文或代码注释等。这些资源通常提供了对源代码更深入的解释和讨论,对于理解ptmalloc2的实现细节会有所帮助。 总之,通过下载并分析glibc内存管理ptmalloc2源代码,可以帮助我们更好地理解和使用glibc库中的内存分配功能。同时,也可以通过分析源代码来提高我们的代码调试和性能优化能力,并为开发更高效的内存管理算法提供参考。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值