当前位置: 首页 > 编程日记 > 正文

TCMalloc:线程缓存的Malloc

转载自: http://shiningray.cn/tcmalloc-thread-caching-malloc.html

作者:Sanjay Ghemawat, Paul Menage

原文

翻译:ShiningRay

动机

TCMalloc要比glibc 2.3的malloc(可以从一个叫作ptmalloc2的独立库获得)和其他我测试过的malloc都快。ptmalloc在一台2.8GHz的P4机器上(对于小对象)执行一次mallocfree大约需要300纳秒。而TCMalloc的版本同样的操作大约只需要50纳秒。malloc版本的速度是至关重要的,因为如果malloc不够快,应用程序的作者就很有可能在malloc之上写一个自己的自由列表。这就可能导致额外的代码复杂度,以及更多的内存占用――除非作者本身非常仔细地划分自由列表的大小并经常从自由列表中清除空闲的对象。

TCMalloc也减少了多线程程序中的锁争用情况。对于小对象,几乎已经达到了零争用。对于大对象,TCMalloc尝试使用粒度较好和有效的自旋锁。ptmalloc同样是通过使用每线程各自的场地来减少锁争用,但是ptmalloc2使用每线程场地有一个很大的问题。在ptmalloc2中,内存可能会从一个场地移动到另一个。这有可能导致大量空间被浪费。例如,在一个Google的应用中,第一阶段可能会为其URL标准化的数据结构分配大约300MB内存。当第一阶段结束后,第二阶段将从同样的地址空间开始。如果第二个阶段被安排到了一个与第一阶段什?用的场地不同的场地,这个阶段不会复用任何第一阶段留下的的内存,并会给地址空间添加另外一个300MB。类似的内存爆炸问题也可以在其他的应用中看到。

TCMalloc的另一个好处是小对象的空间最优表现形式。例如,分配N个8字节对象可能要使用大约8N * 1.01字节的空间。即,多用百分之一的空间。而ptmalloc2中每个对象都使用了一个四字节的头,(我认为)并将最终的尺寸规整为8字节的倍数,最后使用了16N字节。

使用

要使用TCMalloc,只要将tcmalloc通过“-ltcmalloc”链接器标志接入你的应用即可。

你也可以通过使用LD_PRELOAD在不是你自己编译的应用中使用tcmalloc:

   $ LD_PRELOAD="/usr/lib/libtcmalloc.so"

LD_PRELOAD比较讨巧,我们也不十分推荐这种用法。

TCMalloc还包含了一个堆检查器以及一个堆测量器。

如果你更想链接不包含堆测量器和检查器的TCMalloc版本(比如可能为了减少静态二进制文件的大小),你可以接入libtcmalloc_minimal

概览

TCMalloc给每个线程分配了一个线程局部缓存。小分配可以直接由线程局部缓存来满足。需要的话,会将对象从中央数据结构移动到线程局部缓存中,同时定期的垃圾收集将用于把内存从线程局部缓存迁移回中央数据结构中。


TCMalloc将尺寸小于<=
32K的对象(“小”对象)和大对象区分开来。大对象直接使用页级分配器(一个页是一个4K的对齐内存区域)从中央堆直接分配。即,一个大对象总是页对齐的并占据了整数个数的页。

连续的一些页面可以被分割为一系列小对象,而他们的大小都相同。例如,一个连续的页面(4K)可以被划分为32个128字节的对象。

小对象的分配

每个小对象的大小都会被映射到170个可分配的尺寸类别中的一个。例如,在分配961到1024字节时,都会归整为1024字节。尺寸类别这样隔开:较小的尺寸相差8字节,较大的尺寸相差16字节,再大一点的尺寸差32字节,如此类推。最大的间隔(对于尺寸 >= ~2K的)是256字节。

一个线程缓存对每个尺寸类都包含了一个自由对象的单向链表


当分配一个小对象时:

  1. 我们将其大小映射到对应的尺寸类中。
  2. 查找当前线程的线程缓存中相应的自由列表。
  3. 如果自由列表不空,那么从移除列表的第一个对象并返回它。当按照这个快速通道时,TCMalloc不会获取任何锁。这就可以极大提高分配的速度,因为锁/解锁操作在一个2.8GHz Xeon上大约需要100纳秒的时间。

如果自由列表为空:

  1. 从该尺寸类别的中央自由列表(中央自由列表是被所有线程共享的)取得一连串对象。
  2. 将他们放入线程局部的自由列表。
  3. 将新获取的对象中的一个返回给应用程序。

如果中央自由列表也为空:(1) 我们从中央页分配器分配了一连串页面。(2) 将他们分割成该尺寸类的一系列对象。(4) 像前面一样,将部分对象移入线程局部的自由列表中。

大对象的分配

一个大对象的尺寸(> 32K)会被除以一个页面尺寸(4K)并取整(大于结果的最小整数),同时是由中央页面堆来处理的。中央页面堆又是一个自由列表的阵列。对于i < 256而言,第k个条目是一个由k个页面组成的自由列表。第256个条目则是一个包含了长度>= 256个页面的自由列表:


k个页面的一次分配通过在第k个自由列表中查找来完成。如果该自由列表为空,那么我们则在下一个自由列表中查找,如此继续。最终,如果必要的话,我们将在最后一个自由列表中查找。如果这个动作也失败了,我们将向系统获取内存(使用sbrkmmap或者通过在/dev/mem中进行映射)。

如果k个页面的一次分配行为由连续的长度> k的页面满足了,剩下的连续页面将被重新插回到页面堆的对应的自由列表中。

跨度(Span)

TCMalloc管理的堆由一系列页面组成。连续的页面由一个“跨度”(Span)对象来表示。一个跨度可以是已被分配或者是自由的。如果是自由的,跨度则会是一个页面堆链表中的一个条目。如果已被分配,它会是一个已经被传递给应用程序的大对象,或者是一个已经被分割成一系列小对象的一个页面。如果是被分割成小对象的,对象的尺寸类别会被记录在跨度中。

由页面号索引的中央数组可以用于找到某个页面所属的跨度。例如,下面的跨度a占据了2个页面,跨度b占据了1个页面,跨度c占据了5个页面最后跨度d占据了3个页面。


在一个32位的地址空间中,中央阵列由一个2层的基数树来表示,其中根包含了32个条目,每个叶包含了 215个条目(一个32为地址空间包含了 220个 4K 页面,所以这里树的第一层则是用25整除220个页面)。这就导致了中央阵列的初始内存使用需要128KB空间(215*4字节),看上去还是可以接受的。

在64位机器上,我们将使用一个3层的基数树。

解除分配

当一个对象被解除分配时,我们先计算他的页面号并在中央阵列中查找对应的跨度对象。该跨度会告诉我们该对象是大是小,如果它是小对象的话尺寸类别是什么。如果是小对象的话,我们将其插入到当前线程的线程缓存中对应的自由列表中。如果线程缓存现在超过了某个预定的大小(默认为2MB),我们便运行垃圾收集器将未使用的对象从线程缓存中移入中央自由列表。

如果该对象是大对象的话,跨度会告诉我们该对象覆盖的页面的范围。假设该范围是[p,q]。我们还会查找页面p-1和页面q+1对应的跨度。如果这两个相邻的跨度中有任何一个是自由的,我们将他们和[p,q]的跨度接合起来。最后跨度会被插入到页面堆中合适的自由列表中。

小对象的中央自由列表

就像前面提过的一样,我们为每一个尺寸类别设置了一个中央自由列表。每个中央自由列表由两层数据结构来组成:一系列跨度和每个跨度一个自由对象的链表。

通过从某个跨度中移除第一个条目来从中央自由列表分配一个对象。(如果所有的跨度里只有空链表,那么首先从中央页面堆中分配一个尺寸合适的跨度。)

一个对象可以通过将其添加到他包含的跨度的链表中来返回到中央自由列表中。如果链表长度现在等于跨度中所有小对象的数量,那么该跨度就是完全自由的了,就会被返回到页面堆中。

线程缓存的垃圾收集

某个线程缓存当缓存中所有对象的总共大小超过2MB的时候,会对他进行垃圾收集。垃圾收集阈值会自动根据线程数量的增加而减少,这样就不会因为程序有大量线程而过度浪费内存。

我们会遍历缓存中所有的自由列表并且将一定数量的对象从自由列表移到对于得中央列表中。

从某个自由列表中移除的对象的数量是通过使用一个每列表的低水位线L来确定的。L记录了自上一次垃圾收集以来列表最短的长度。注意,在上一次的垃圾收集中我们可能只是将列表缩短了L个对象而没有对中央列表进行任何额外访问。我们利用这个过去的历史作为对未来访问的预测器并将L/2个对象从线程缓存自由列表中移到相应的中央自由列表中。这个算法有个很好的特性是,如果某个线程不再使用某个特定的尺寸时,该尺寸的所有对象都会很快从线程缓存被移到中央自由列表,然后可以被其他缓存利用。

性能备注

PTMalloc2单元测试

PTMalloc2包(现在已经是glibc的一部分了)包含了一个单元测试程序t-test1.c。它会产生一定数量的线程并在每个线程中进行一系列分配和解除分配;线程之间没有任何通信除了在内存分配器中同步。

t-test1(放在tests/tcmalloc/中,编译为ptmalloc_unittest1)用一系列不同的线程数量(1~20)和最大分配尺寸(64B~32KB)运行。这些测试运行在一个2.4GHz 双核心Xeon的RedHat 9系统上,并启用了超线程技术, 使用了Linux glibc-2.3.2,每个测试中进行一百万次操作。在每个案例中,一次正常运行,一次使用LD_PRELOAD=libtcmalloc.so

下面的图像显示了TCMalloc对比PTMalloc2在不同的衡量指标下的性能。首先,现实每秒全部操作(百万)以及最大分配尺寸,针对不同数量的线程。用来生产这些图像的原始数据(time工具的输出)可以在t-test1.times.txt中找到。

  • TCMalloc要比PTMalloc2更具有一致地伸缩性——对于所有线程数量>1的测试,小分配达到了约7~9百万操作每秒,大分配降到了约2百万操作每秒。单线程的案例则明显是要被剔除的,因为他只能保持单个处理器繁忙因此只能获得较少的每秒操作数。PTMalloc2在每秒操作数上有更高的方差——某些地方峰值可以在小分配上达到4百万操作每秒,而在大分配上降到了<1百万操作每秒。
  • TCMalloc在绝大多数情况下要比PTMalloc2快,并且特别是小分配上。线程间的争用在TCMalloc中问题不大。
  • TCMalloc的性能随着分配尺寸的增加而降低。这是因为每线程缓存当它达到了阈值(默认是2MB)的时候会被垃圾收集。对于更大的分配尺寸,在垃圾收集之前只能在缓存中存储更少的对象。
  • TCMalloc性能在约32K最大分配尺寸附件有一个明显的下降。这是因为在每线程缓存中的32K对象的最大尺寸;对于大于这个值得对象TCMalloc会从中央页面堆中进行分配。

下面,CPU时间的每秒操作数(百万)以及线程数量的图像,最大分配尺寸64B~128KB。

这次我们再一次看到TCMalloc要比PTMalloc2更连续也更高效。对于<32K的最大分配尺寸,TCMalloc在大线程数的情况下典型地达到了CPU时间每秒约0.5~1百万操作,同时PTMalloc通常达到了CPU时间每秒约0.5~1百万,还有很多情况下要比这个数字小很多。在32K最大分配尺寸之上,TCMalloc下降到了每CPU时间秒1~1.5百万操作,同时PTMalloc对于大线程数降到几乎只有零(也就是,使用PTMalloc,在高度多线程的情况下,很多CPU时间被浪费在轮流等待锁定上了)。

注意

对于某些系统,TCMalloc可能无法与没有链接libpthread.so(或者你的系统上同等的东西)的应用程序正常工作。它应该能正常工作于使用glibc 2.3的Linux上,但是其他OS/libc的组合方式尚未经过任何测试。

TCMalloc可能要比其他malloc版本在某种程度上更吃内存,(但是倾向于不会有其他malloc版本中可能出现的爆发性增长。)尤其是在启动时TCMalloc会分配大约240KB的内部内存。

不要试图将TCMalloc载入到一个运行中的二进制程序中(例如,在Java中使用JNI)。二进制程序已经使用系统malloc分配了一些对象,并会尝试将它们传递到TCMalloc进行解除分配。TCMalloc是无法处理这种对象的。

相关文章:

今年央视的春晚能给人带来惊喜吗?

已经好多年还没看完中央电视台的春节联欢晚会自己就睡着了&#xff0c;说实在的&#xff0c;现在央视春节联欢晚会的节目总是让人期待后感到相当的平淡乏味&#xff0c;有些搞笑节目庸俗的让人笑不出来&#xff0c;绝大多数的节目都显得非常的人工&#xff0c;全然不能激发出观…

将baidu地图中的baidu logo去掉

Web 最简单方法&#xff0c;将logo的css样式改为display:none即可 <!DOCTYPE html> <html> <head><meta charset"utf-8" /><title>移除百度地图LOGO和版权信息</title><script type"text/javascript" src"htt…

Linux环境网络库

安装libevent 官网&#xff1a;http://libevent.org/ 书籍&#xff1a;http://www.wangafu.net/~nickm/libevent-book/ Libevent参考手册翻译:http://blog.csdn.net/laoyi19861011/article/category/831215 Libevent参考手册翻译增加&#xff1a;http://blog.sina.co…

万人马拉松赛事,人脸识别系统如何快速、准确完成校验?

作者 | 阿里文娱技术专家墨贤出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;大麦的人脸闸机在2019年杭州马拉松上成功的完成了刷脸入场功能的首秀&#xff0c;相比传统的马拉松入场核验方案在入场体验和入场效率上都有了很大的提升&#xff0c;下面介绍一下大麦的人…

Collection集合List、Set

Collection集合&#xff0c;用来保存一组数据的数据结构。 Collection是一个接口&#xff0c;定义了所有集合都应该包含的特征和行为 Collection派生出了两类集合 List和Set List接口&#xff1a;List集合的特征是元素是可重复且有序 Set接口&#xff1a;Set集合的特征是元素是…

如何用Jupyter Notebook制作新冠病毒疫情追踪器?

出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;新冠肺炎已在全球范围内爆发。为了解全球疫情分布情况&#xff0c;有技术人员使用Jupyter Notebook绘制了两种疫情的等值线地图&#xff08;choropleth chart&#xff09;和散点图。前者显示了一个国家/地区的疫情扩散…

关于Aptana studio工具

今天&#xff0c;使用了Aptana studio这个工具&#xff0c;界面类似于Myeclipse因使用MyEclipse比较顺手&#xff0c;这个工具上手还挺容易的。而且比Dreamweaver好用多了&#xff0c;有代码提示的工具&#xff0c;再加上工具不大&#xff0c;耗内存较小。挺喜欢这个工具的。写…

再谈JSON -json定义及数据类型

再谈json 近期在项目中使用到了highcharts ,highstock做了一些统计分析。使用jQuery ajax那就不得不使用json, 可是在使用过程中也出现了非常多的疑惑&#xff0c;比方说&#xff0c;什么情况下我们须要去将字符串转换为json对象。什么情况下就不须要转换。通过hql和sql查询返回…

Linux软连接和硬链接

1.Linux链接概念 Linux链接分两种&#xff0c;一种被称为硬链接&#xff08;Hard Link&#xff09;&#xff0c;另一种被称为符号链接&#xff08;Symbolic Link&#xff09;。默认情况下&#xff0c;ln命令产生硬链接。 【硬连接】 硬连接指通过索引节点来进行连接。在Linux的…

学语言不是写程序!

这是发到我邮箱里面的一封信&#xff0c;嗯&#xff0c;类似的信有好几封&#xff0c;春节期间呢&#xff0c;我主要陪笑笑&#xff0c;呵呵&#xff0c;不办公&#xff0c;就一直压着没有回答&#xff0c;有点delay了&#xff0c;现在给这几位同学抱个歉哈&#xff0c;对不住了…

“AI”战疫在行动,一文盘点百度大脑增援疫情防控的AI操作

2020年春节&#xff0c;注定将刻进每个人的记忆。面对突如其来的新型冠状病毒感染的肺炎疫情&#xff0c;除了一线医护人员的日夜奋战&#xff0c;“人工智能”也在特殊时期走向前沿&#xff0c;接受了抗疫洗礼。 3月13日&#xff0c;今年第一期百度大脑开放日首次通过直播的形…

POJ 2778 AC自己主动机+矩阵幂 不错的题

http://poj.org/problem?id2778 有空再又一次做下&#xff0c;对状态图的理解非常重要 题解&#xff1a; http://blog.csdn.net/morgan_xww/article/details/7834801 另外做了矩阵幂的模板&#xff1a; //ac.sz是矩阵的大小 void mulmtr(long long x[MAXNODE][MAXNODE],long l…

Libevent调用

1.最基本的打印libevent版本 #include <event.h> #include <stdio.h>int main() {const char *version event_get_version();printf("%s\n",version);return 0; }# gcc getVersion.c -o getVersion -levent 参考&#xff1a;https://github.com/mike-zh…

如何更新你的机器学习模型?手把手带你设计一个可持续的预测模型!

作者 | CloudFactory译者 | 天道酬勤 责编 | 徐威龙出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;高效的机器学习模型需要高质量的数据。训练你的机器学习模型并不是过程中的单个有限阶段。即使将其部署到生产环境中&#xff0c;也可能需要稳定的新训练数据流来确保…

占失物,笔记本电脑电池

公历&#xff1a;2009年3月18日18时11分 农历&#xff1a; 农历己丑年(牛)二月廿二 节气&#xff1a; 2009年3月5日19时2分惊蛰年建&#xff1a;己丑 月建&#xff1a;丁卯 日建&#xff1a;壬戌 时建&#xff1a;己酉 断:玄武中值天地合,故能寻到,在西方,又为长生之地,故为住…

Scala Learn 1 Basic

Chap 0 前言 focus on: Scala 的语法十分简洁Scala 运行在虚拟机之上, 可以使用 java 的海量类库和工具Scala 拥抱函数式编程的同时&#xff0c;并没有废弃面向对象Scala 既有动态语言那样的灵活简洁&#xff0c;同时有保留了静态类型检查的安全与执行效率Scala 既能处理脚本化…

linux下使用NetBeans调试libevent库

1.安装libevent 参考&#xff1a;http://blog.csdn.net/unix21/article/details/8679269 libevent安装在usr/local/libevent下 2.安装netBeans http://www.netbeans.org 3.配置netBeans 1)打开项目的属性选项&#xff0c;选择包含目录&#xff0c;把/usr//local/libevent/…

批量删除指定文件

Linux下的解决方法: # Linux Batch Delete find /home/data/-name ab.doc-exec rm -f {} \;注&#xff1a;最后反斜杠前有一空格&#xff0c;最后一个是分号。Windows下的解决方法:rem Windows Batch Delete 1: DEL /Q /S D:\home\data\*.class 2: FOR /R D…

百万人学AI:CSDN重磅共建人工智能技术新生态

站在AI发展的新十年起点上&#xff0c;CSDN将发挥开发者优势&#xff0c;与中国AI各行业和企业共建“百万人学AI”新技术生态。 作者 | CSDN新媒体事业部 8年前&#xff0c;现图灵奖得主Hinton团队在ImageNet竞赛中首次使用深度学习完胜Google等其它团队&#xff0c;顿时让工…

Android Property Animation属性动画:scale缩放动画(4)

&#xfeff;&#xfeff;Android Property Animation属性动画&#xff1a;scale缩放动画&#xff08;4&#xff09; 和之前我写的附录文章1,2,3相似&#xff0c;本文将接着使用Android Property Animation属性动画实现一个缩放的动画。代码部分和文章1,2,3中的代码大同小异&am…

结构体的两种声明方式:堆上和栈上以及在双链表的应用

在看《算法精解&#xff1a;C语言描述》的双链表chtbl和redis的双链表adlist.c发现代码思路基本是一致的。 但是&#xff0c;对于链表的初始化却不一样 1.《算法精解&#xff1a;C语言描述》风格 /************************************************************************…

COM 组件设计与应用(六)——用 ATL 写第一个组件(vc.net)

一、前言 1、与 《COM 组件设计与应用(五)》的内容基本一致。但本回讲解的是在 vc.net 2003 下的使用方法&#xff0c;即使你不再使用vc6.0&#xff0c;也请和上一回的内容&#xff0c;参照比对。2、这第一个组件&#xff0c;除了所有 COM 组件必须的 IUnknown 接口外&#xff…

《评人工智能如何走向新阶段》后记(再续19)

由AI科技大本营下载自视觉中国304. 也来讨论构建模拟人类思维过程的认知计算机制&#xff0c;好像这个问题迄今尚未获得解决。 我们先从输入的信息类型说起&#xff1a;一类是语言输入&#xff08;包括词、句、文本&#xff09;&#xff0c;第二类是图像输入&#xff08;包括图…

PHP下载/采集远程图片到本地

2019独角兽企业重金招聘Python工程师标准>>> PHP下载/采集远程图片到本地01 /** 02* 下载远程图片到本地 03* 04* param string $url 远程文件地址 05* param string $filename 保存后的文件名&#xff08;为空时则为随机生成的文件名&#xff0c;否则为原文件名&am…

Linux守护进程实现

Linux守护进程 redis版&#xff1a; void daemonize(void) {int fd;if (fork() ! 0) exit(0); /* parent exits */setsid(); /* create a new session *//* Every output goes to /dev/null. If Redis is daemonized but* the logfile is set to stdout in the configuration …

美团十年,支撑最大规模外卖配送的一站式机器学习平台如何炼成?

作者 | 艳伟&#xff0c;美团配送技术团队资深技术专家编辑 | 唐小引题图 | 东方 ICAI 是目前互联网行业炙手可热的“明星”&#xff0c;无论是老牌巨头&#xff0c;还是流量新贵&#xff0c;都在大力研发 AI 技术&#xff0c;为自家的业务赋能。配送作为外卖平台闭环链条上重要…

Windows 2008 R2中的NAP新功能详解

随着Windows Server 2008 R2版本的发布&#xff0c;Windows网络访问保护模式&#xff08;NAP&#xff09;又增加了新功能。在本文中&#xff0c;笔者将对新功能进行简要的介绍。Windows Server 2008中提供的网络访问保护(NAP)功能已经更新到R2版本。在Windows功能、无线网络访问…

whoosh学习(1)

2019独角兽企业重金招聘Python工程师标准>>> 背景 当前项目需要用到全文搜索redis不方便实现mysql效率太低搜索引擎选择 pylucenewhoosh&#xff08;似乎更受欢迎&#xff0c;文档最全&#xff09;为什么选择 纯python实现&#xff0c;省了编译二进制包的繁琐过程。…

仿照redis写的nginx开机画面

redis有一个开机画面&#xff1a; 下面是我写的的nginx开机画面&#xff1a; 新建一个文件 asciilogo.h //仿照redis风格打印一个logo,这样启动的时候就不会不注意 char *ascii_logo " …