tcmalloc原理分析

  1. tcmalloc(即Thread-Cache Malloc)是一个通用的内存分配器,使用tcmalloc只需要在编译的链接阶段加入-ltcmalloc,而不是使用glibc(ptmalloc2),不需要有任何的代码改动。也就是说用户在使用malloc/free、new/delete时会使用tcmalloc进行内存分配。
  2. 为什么要使用tcmalloc

主要是因为性能,tcmalloc能提供更快的申请/释放速度,而且内存利用率更高,产生更少的内存碎片

  1. 原理:先上图

    1. 基本概念:

Free List:数组链表,链表中保存了内存块

objects:内存块

Page:页内存,内存分隔成大小固定,地址对齐的块

Span:tcmalloc管理内存的单位,一个Span可以包含一个或多个Page

Radix Tree:基数树,是一种广泛用于内存管理的数据结构,这里用来管理Span

?

    1. 组织结构:

tcmalloc以256k为界将内存分成大块内存和小块内存,使用不同的策略分别对这两种内存进行管理。从图中可以看到,tcmalloc由若干(线程数)个Thread Cache,一个Central Heap和一个Page Heap组成。这三种结构中都包含一个数组,而数组的元素是一个链表。数组链表是tcmalloc管理内存的主要数据结构之一。三者所不同的是,Thread Cache的链表(FreeList)内容是object,是被切分的小的内存块;Central Heap(FreeList)和Page Heap(SpanList)的链表内容是Span,但Central Heap的Span中又有切分的object。

    1. 小内存的分配策略

小内存的管理由两部分构成:Thread Cache和Central Heap。其中Thread Cache是线程本地Cache,每个线程一个;Central Heap则由所有线程共享。

当一个线程申请内存时,首先响应的是Thread Cache,如 大专栏  tcmalloc原理分析果其中有足够大的内存满足要求,可直接返回。只有当内存不够时,需要向Central Heap申请,此时使用了一个细粒度的自旋锁来保证线程安全。如果Central Heap没有足够内存该怎么办呢,后面会讲到具体策略。

?

由上可知,小内存的分配在大部分情况下都是预分配好的,可以拿来即用,只有在本地Cache不足的情况才需要加锁,因此效率很高。

    1. 大内存的分配策略

大内存通过Page Heap来管理内存,策略与小内存相似,也是预分配好一个数组链表,不同的是Page Heap只有一个,而且实际上Central Heap的Span也是从Page Heap上分配出去的。

Page Heap的数组共256项,每项中的Span依次包含1-255个Page,最后一项的Span包含大于等于256个Page。当数组中的第k项已经没有Span时,可以从第k+1项拿一个Span,将这个Span拆成一个包含k个Page的Span提供给申请者,一个包含1项的Span放到数组的第1项中。如果第k+1项同样没有Span则继续项第k+2项申请,依次类推。

    1. 内存回收

???????? 当释放一个内存对象时,需要先根据地址计算出页号,再在Radix Tree中找到页号对应的Span,根据Span确定是小内存还是大内存对象。
???????? 如果是小内存,需要把它插入内存本地的FreeList中,如果线程本地内存cache超过阈值(默认2MB),会使用策略将部分未使用的内存块移动到Central Heap中,此时放到了central cache中的tc_slots_中,而不是直接放入Span中,只有当tc_slots_满了,才会归还到Span中,这样的好处是在Thread Cache和Central Heap中又加入了一层缓存使效率更高。
???????? 如果是大内存,还要获取这个Span页的前一页和后一页是否空闲,如果都不空闲,则直接将这个Span放入SpanList合适的位置,如果这个Span的前一页或后一页存在空闲,还需要将这个Span与前面或后面的Span合并后再把新的Span放入合适的SpanList中。例如,Span1包含[m, n-1]页,Span2包含[n, k-1]页,Span3包含[k, s]页,此时回收了Span2,如果检查发现第n-1页空闲,第k页非空闲,此时需要将Span1和Span2合并成一个包含[m, k-1]页的新Span,而如果第n-1页和第k页都空闲的话,则合并后的新Span应包含[m,s]页。
4.?? ?后记
???????? 使用tcmalloc后,不必再费尽心思去在代码中设计内存池,而且使用时不需要包含任何头文件,只需要在链接环节使用-ltcmalloc代替glibc即可,这是作为一款通用内存管理器的便捷之处。同时在效率上可以得到数倍的提升。
???????? 其实tcmalloc中还有很多细节值得研究,我们应该学习其中优秀的编程思想,同时也希望通过以上分析对理解tcmalloc有所帮助。

?

?

原文地址:https://www.cnblogs.com/wangziqiang123/p/11696929.html

时间: 2024-10-30 06:43:50

tcmalloc原理分析的相关文章

kafka producer实例及原理分析

1.前言 首先,描述下应用场景: 假设,公司有一款游戏,需要做行为统计分析,数据的源头来自日志,由于用户行为非常多,导致日志量非常大.将日志数据插入数据库然后再进行分析,已经满足不了.最好的办法是存日志,然后通过对日志的分析,计算出有用的数据.我们采用kafka这种分布式日志系统来实现这一过程. 步骤如下: 搭建KAFKA系统运行环境 如果你还没有搭建起来,可以参考我的博客: http://zhangfengzhe.blog.51cto.com/8855103/1556650 设计数据存储格式

android脱壳之DexExtractor原理分析[zhuan]

http://www.cnblogs.com/jiaoxiake/p/6818786.html内容如下 导语: 上一篇我们分析android脱壳使用对dvmDexFileOpenPartial下断点的原理,使用这种方法脱壳的有2个缺点: 1.  需要动态调试 2.  对抗反调试方案 为了提高工作效率, 我们不希望把宝贵的时间浪费去和加固的安全工程师去做对抗.作为一个高效率的逆向分析师, 笔者是忍不了的,所以我今天给大家带来一种的新的脱壳方法——DexExtractor脱壳法. 资源地址: Dex

android脱壳之DexExtractor原理分析

导语: 上一篇我们分析android脱壳使用对dvmDexFileOpenPartial下断点的原理,使用这种方法脱壳的有2个缺点: 1.  需要动态调试 2.  对抗反调试方案 为了提高工作效率, 我们不希望把宝贵的时间浪费去和加固的安全工程师去做对抗.作为一个高效率的逆向分析师, 笔者是忍不了的,所以我今天给大家带来一种的新的脱壳方法--DexExtractor脱壳法. 资源地址: DexExtractor源码:https://github.com/bunnyblue/DexExtracto

Adaboost算法原理分析和实例+代码(简明易懂)

Adaboost算法原理分析和实例+代码(简明易懂) [尊重原创,转载请注明出处] http://blog.csdn.net/guyuealian/article/details/70995333     本人最初了解AdaBoost算法着实是花了几天时间,才明白他的基本原理.也许是自己能力有限吧,很多资料也是看得懵懵懂懂.网上找了一下关于Adaboost算法原理分析,大都是你复制我,我摘抄你,反正我也搞不清谁是原创.有些资料给出的Adaboost实例,要么是没有代码,要么省略很多步骤,让初学者

Android视图SurfaceView的实现原理分析

附:Android控件TextView的实现原理分析 来源:http://blog.csdn.net/luoshengyang/article/details/8661317 在Android系统中,有一种特殊的视图,称为SurfaceView,它拥有独立的绘图表面,即它不与其宿主窗口共享同一个绘图表面.由于拥有独立的绘图表面,因此SurfaceView的UI就可以在一个独立的线程中进行绘制.又由于不会占用主线程资源,SurfaceView一方面可以实现复杂而高效的UI,另一方面又不会导致用户输

AbstractQueuedSynchronizer的介绍和原理分析(转)

简介 提供了一个基于FIFO队列,可以用于构建锁或者其他相关同步装置的基础框架.该同步器(以下简称同步器)利用了一个int来表示状态,期望它能够成为实现大部分同步需求的基础.使用的方法是继承,子类通过继承同步器并需要实现它的方法来管理其状态,管理的方式就是通过类似acquire和release的方式来操纵状态.然而多线程环境中对状态的操纵必须确保原子性,因此子类对于状态的把握,需要使用这个同步器提供的以下三个方法对状态进行操作: java.util.concurrent.locks.Abstra

linux中mmap系统调用原理分析与实现

参考文章:http://blog.csdn.net/shaoguangleo/article/details/5822110 linux中mmap系统调用原理分析与实现 1.mmap系统调用(功能)      void* mmap ( void * addr , size_t len , int prot , int flags ,int fd , off_t offset )      内存映射函数mmap, 负责把文件内容映射到进程的虚拟内存空间, 通过对这段内存的读取和修改,来实现对文件的

Android 4.4 KitKat NotificationManagerService使用详解与原理分析(一)__使用详解

概况 Android在4.3的版本中(即API 18)加入了NotificationListenerService,根据SDK的描述(AndroidDeveloper)可以知道,当系统收到新的通知或者通知被删除时,会触发NotificationListenerService的回调方法.同时在Android 4.4 中新增了Notification.extras 字段,也就是说可以使用NotificationListenerService获取系统通知具体信息,这在以前是需要用反射来实现的. 转载请

一个日期算法的原理分析

1.问题描述 在 OSC 问答频道有一个问题:时间算法:帮忙解答下 简单的复述一遍就是能够通过如下式子来计算month月day日是一年的第几天. 闰年是 day_of_year=(275*month)/9 - (month+9)/12 + day - 30 非闰年比这个少1天.可以简单的验证,这个式子中每个部分计算后都取整,整个结果总是对的. 我们知道1.3.5.7.8.10.12都是31天,2月的天数有点诡异,其他都是30天,正常情况下我们写程序会写很多if来判断月份,进而计算累积的天数.但是