昨天聊的64MB内存中,有使用TCMalloc,但是对其原理不是很了解,所以学习了下。

前言

先不使用TCMalloc,先使用glibc自带的内存分配ptmalloc2进行内存分配,先看一个简单的程序:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>int main( int argc, char *argv[] )
{malloc(1);getchar();
}

编译运行:

gcc -g m.c -o m
./m

查看下我们申请一个字节的内存占用情况:

[root@izbp14xswj2tx6qgnz9dllz ~]# cat /proc/2888/maps|grep heap
00ed3000-00ef4000 rw-p 00000000 00:00 0                                  [heap]
[root@izbp14xswj2tx6qgnz9dllz ~]# python
Python 2.7.5 (default, Aug  4 2017, 00:39:18)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-16)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 0x00ef4000-0x00ed3000
135168
>>> 135168/1024
132

结论我们申请1个字节的内存,实际内存分配器给我们分配了132KB的内存,这样做出是下次再申请内存的时候,如果小于132KB内存,不用再向系统申请,加快内存分配速度。即时我们把代码改成如下:

char * p = (char*)  malloc(1);
free(p);

申请的内存仍然不释放:

[root@izbp14xswj2tx6qgnz9dllz ~]# cat /proc/3248/maps|grep heap
022ce000-022ef000 rw-p 00000000 00:00 0                                  [heap]
[root@izbp14xswj2tx6qgnz9dllz ~]# python
Python 2.7.5 (default, Aug  4 2017, 00:39:18)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-16)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> (0x022ef000-0x022ce000)/1024
132

一  简介

TCMalloc 库全称Thread-Caching Malloc 是谷歌开源工具google-perftools中的成员,是一个内存分配器,这个内存分配器与我们上面说的linux系统下默认的glibc中的ptmalloc2内存分配器有什么不同那。主要优点:

  • tcmalloc 一次malloc或free操作更快,据说ptmalloc2需要300ns,tcmalloc 需要50ns。

  • tcmalloc 优化小对象的存储,需要更少的空间。

  • tcmalloc 对多线程分配内存,小对象基本不存在锁竞争,因为分配器会给现场分配本地缓存,长期空闲的情况下也不会被回收。

二  分配策略

在TCMalloc 对于不同申请内存的大小采用不同的策略,内存大小划分如下:

  1. (0,256KB] 属于小内存;

  2. (256KB,1MB] 属于中等内存;

  3. (1M, +∞] 属于大内存。在TCMalloc 中内存分配粒度有两种一种是Object,大小是预设的规则,比如8字节,16字节,32字节,48字节等;另一种叫Span,一个Span是由多个Page组成,Object 是由Span切出来的。

2.1  Thread Cache

对于小内存分配,是在Thread Cache中分配的,为了减少内存碎片,TCMalloc按大小划分了85个类别,这些称为Size Class,每个Size Class都对应固定字节的大小,从8个字节,到16个字节...一直到256K,这些 Thread Cache采用双向链表形式串联起来,由于Thread Cache 是每个线程都有的,所以多线程同时分配内存的时候,如果Thread Cache 对应的Size Class中相应大小是空闲,就不用加锁,比如我们申请15B内存,这个线程的Thread Cache中从Size Class中的16字节对应的free list中分配内存。

Thread Cache

Thread Cache 在整个分配器中是个双向链表,每个都对应一个空闲内存池。每个线程的Thread Cache大小限制最大4MB,大小在512KB-4MB之间。所有线程Thread Cache的总大小默认限制为32MB,取值范围从512KB到1GB之间。

2.2 Central Cache

Central Cache是所有线程公用的缓存,Central Cache对于每个Size Class 都由一个独立的链表来缓存空闲对象,当Thread Cache中内存不够的时候,从中获取,由于是所有线程公用的,所以从中取或归还对象的时候,需要加锁的,一般Thread Cache一次获取或归还多个空闲对象。

Central Cache

2.3 Page Heap

如果Central Cache的内存不够的话,会向Page Heap申请。申请好的内存,将其拆分成一系列空闲对象,添加对应size class对应的free list中。Page Heap的内存结构是以span为单位组织的,每个span由不同的page 组成,Page Heap按照大小分为1page 对应span,2个pages对应span,一直到128个pages 对应的span,即128*8KB= 1024KB即1M,注意这里面的page为8KB(可以调整默认为8KB)。大小超过1M的,即超过128个pages的span存储在有序的set中,如下图:

2.4 小对象的分配策略

  • 将要分配的内存向上取到对应的size class对应的队列中。

  • 如果该线程的Thread Cache 对应的size class的free list 非空,取出一个空闲对象 返回。

  • 如果该线程对应的size class的free list为空,则向 Central Cache申请内存:

    • 则向page heap 申请一个span (page heap不够,则向系统申请内存)。

    • 将span拆分成若干个size class对象。

    • 如果 Central Cache对应的size class 有空闲对象,则取一些空闲对象。

    • 如果Central Cache对应的size class 中也无空闲对象:

  • 将申请到的size class 放到Thread Cache 的空闲队列中,返回一个空闲对象。

2.5 中间对象的分配策略

即大于256KB 小于1MB内存的分配,分配的内存是直接从 page heap上选取与申请内存向上对应的span,比如申请内存3.5个pages,则直接从 4个pages 对应的span查找。假设向上对应的为k个pages:

  • 在 k pages 对应的span空闲队列查找,如果没有就向下找 k+1 个pages对应的span。

  • 直到找到一个非空的n个pages对应的空闲span或者找到了128个pages对应的span

    • 从这个找到的n个pages对应的span中切出 k个pages 作为申请内存结果返回。

    • 将剩下的n-k个pages 对应的span插入到相应的空闲队列中。

  • 如果找不到合适的span,则算大对象。

2.6 大对象的内存分配策略

同样是在page heap中分配,由于申请的内存大于128个pages,所以需要在page heap的set里面去找合适的n个pages对应的span。

  • 如果找到,拆分:

    • 一个span大小为k 个page,返回。

    • 剩下n- k个pages,如果n-k> 128,仍然放在set中,小于则放在对应的小span中。

  • 如果找不到,则需要向系统申请内存,申请内存以span为单位。

2.7 内存回收

当应用程序释放内存给Thread Cache,会回收到free list中,如果free list中内存达到一定程度后,会返回给Central Cache中,如果一个span中的所有对象都回收了,则再将span返还给page heap, page heap在合适时机返回给系统。

三 C 程序使用TCMalloc

编译链接下tcmalloc库,就可以了,通过下面的方法验证下:

[root@localhost testcode]# g++ -g -ltcmalloc m.c -o m
[root@localhost testcode]# ./m
^C
[root@localhost testcode]# vim m.c
[root@localhost testcode]# gdb ./m
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-100.el7
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/miaohq/testcode/m...done.
(gdb) b 7
Breakpoint 1 at 0x40071c: file m.c, line 7.
(gdb) r
Starting program: /home/miaohq/testcode/./m
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib64/libthread_db.so.1".Breakpoint 1, main (argc=1, argv=0x7fffffffe118) at m.c:7
7       malloc(1);
Missing separate debuginfos, use: debuginfo-install glibc-2.17-196.el7_4.2.x86_64 libgcc-4.8.5-39.el7.x86_64 libstdc++-4.8.5-39.el7.x86_64
(gdb) s
tc_malloc (size=1) at src/tcmalloc.cc:1892

四 诗词欣赏

八声甘州·自王家无怨住襄城[宋] [魏了翁]自王家无怨住襄城,世总生贤。
似谢阶兰玉,马庭梧竹,一一堪怜。
富贵关人何事,且问此何缘。又
踏前朝脚,领蜀山川。
点检重关复阁,尚甘棠匝地,乔木参天。
中兴规画,父老至今传。
六十年、山河未改,只芳菲、不断紧相联。
相将又,参陪宰席,还似当年。

TCMalloc 简介相关推荐

  1. TCmalloc学习

    目录 TCmalloc简介 TCMalloc内部结构 TCMalloc 的工作模式 tcmalloc申请内存流程 tcmalloc释放内存流程 TCmalloc简介 TCMalloc 是 Google ...

  2. tcmalloc性能测试

    一 tcmalloc简介 1.tcmalloc(thread-caching malloc),即线程缓存malloc,为每个线程分配本地的cache: 2.线程所需的小对象(几十个字节到1K左右)都从 ...

  3. C++性能优化(九) —— TCMalloc

    一.TCMalloc简介 1.TCMalloc简介 TCMalloc(Thread-Caching Malloc,线程缓存的malloc)是Google开发的内存分配算法库,最初作为Google性能工 ...

  4. 一文搞定google perftool

    文章目录 使用背景 TCMalloc 简介 TCMalloc 与 gperftools gperftools使用 gperftools 安装 编译安装libunwind 编译安装perftools 将 ...

  5. 死磕GC:Java GC 和 GO GC 大对比,看完秒成高高手

    说在前面 现在拿到offer超级难,甚至连面试电话,一个都搞不到. 尼恩的技术社群中(50+),很多小伙伴凭借 "左手云原生+右手大数据"的绝活,拿到了offer,并且是非常优质的 ...

  6. 内存分配器ptmalloc,jemalloc,tcmalloc调研与对比

    内存分配器ptmalloc,jemalloc,tcmalloc调研与对比 rtoax 2020年12月 1. 概述 内存管理不外乎三个层面,用户程序层,C运行时库层,内核层.allocator 正是值 ...

  7. tcmalloc内存分配器分析笔记:基于gperftools-2.4

    目录 一. SizeMap 二. 线程缓存ThreadCache ThreadCache的实现 1. 内存分配 2. 内存释放 三. 中央缓存Central Cache CentralFreeList ...

  8. TCMalloc内存分配器如何减少内存碎片?

    目录 前言 什么是内存碎片? 内存碎片-Freelist 内存碎片-Segregated-Freelist 内存碎片-Buddy-System 内存分配算法的比较 TCMalloc的内存碎片 TCMa ...

  9. ptmalloc、tcmalloc与jemalloc内存分配器对比分析

    目录 背景介绍 ptmalloc 系统向看ptmalloc内存管理 用户向看ptmalloc内存管理 线程中内存管理 Chunk说明 tcmalloc 系统向看tcmalloc内存管理 用户向看tcm ...

最新文章

  1. 杭电2063--过山车(二分匹配)
  2. Nxt节点安装指南之RaspberryPi树莓派版
  3. 8086汇编 贪吃蛇 源代码
  4. 树莓派3B+,我要跑.NET CORE
  5. 【SR汇总】基于深度学习方法
  6. 程序员在群询问破解软件
  7. Windows守护进程简单示例
  8. LabVIEW自带函数实现SQL Server操作(上)
  9. 实现加载页Loading Page 的几种方法
  10. Linux服务器上修改深度学习代码
  11. React脚手架搭建及创建React项目
  12. linux安装vim失败(Unable to locate package vim)
  13. 【深度学习】使用opencv在视频上添加文字和标记框
  14. Axure获取焦点和触发事件
  15. SuperMap iServer服务器安全性最优做法
  16. HTML控件事件一览表
  17. 中文转拼音 java_Java中文转拼音
  18. 点焊机器人焊接超时_机器人点焊自动化 I 附机器人点焊焊接工艺
  19. CIE1931-XYZ表色系统
  20. 语法基础课——第一讲 习题

热门文章

  1. 点云最小二乘法拟合曲线
  2. Redis相关命令及使用场景介绍
  3. 剑指Offer(10)有环链表 翻转链表
  4. MLAPP翻译---第二章
  5. C语言 第八章 函数
  6. python 操作psd_怎样用python实现对PSD-BPA的调用?
  7. 原生JS 表单提交验证器
  8. 最新ICCV 2021 | 虚拟试衣(21)图像编辑-文本引导(22)图像编辑-单样本(23)生成对抗GAN...
  9. 计算机机房空调检查,大型计算机机房空调设计模拟研究
  10. 运营QQ公众平台的正确姿势