精华内容
下载资源
问答
  • TCMalloc

    2021-06-17 15:08:55
    TCMalloc 是Google开发的内存分配器。全称Thread-Caching Malloc,即线程缓存的malloc,实现了高效的多线程内存管理,用于替代系统的内存分配相关的函数(malloc、free,new,new[]等)。 TCMalloc 可以分为三部分...

    TCMalloc 是Google开发的内存分配器。全称Thread-Caching Malloc,即线程缓存的malloc,实现了高效的多线程内存管理,用于替代系统的内存分配相关的函数(malloc、free,new,new[]等)。

    TCMalloc 可以分为三部分: 前端(front-end)、中端(middle-end)、后端(back-end)。

    * 前端是一个缓存,为应用程序快速提供内存分配和内存解除。

    * 中端负责为前端补充缓存。

    * 后端从系统OS中获取内存。

    注释:前端能运行在per-CPU 或者传统的per-thread 模式,后端能支持 hugepage aware pageheap 和 legacy pageheap。

    *   The front-end is a cache that provides fast allocation and deallocation of
        memory to the application.
    *   The middle-end is responsible for refilling the front-end cache.
    *   The back-end handles fetching memory from the OS.

    [tcmalloc_internals]

     

    前端(Front-end):

     

    This cache is only accessible by a single thread at a time, so it does not require any locks, hence most allocations and deallocations are fast.

    前端有两种实现方式:

    *   Originally it supported per-thread caches of objects (hence the name Thread Caching Malloc). However, this resulted in memory footprints that scaled with the number of threads. Modern applications can have large thread counts, which result in either large amounts of aggregate per-thread memory,
        or many threads having minuscule per-thread caches.
    *   More recently TCMalloc has supported per-CPU mode. In this mode each logical CPU in the system has its own cache from which to allocate memory. Note: On x86 a logical CPU is equivalent to a hyperthread.
    
    per-thread:
    [per-thread-structure.png]
    per-CPU:
    [per-cpu-cache-internals.png]
    
    
    * Small and Large Object Allocation
    * Deallocation 
    * Per-CPU Mode
    * Restartable Sequences and Per-CPU TCMalloc
    * Legacy Per-Thread mode
    * Runtime Sizing of Front-end Caches
    

    中端(Middle-end)

    中端的任务是给前端提供内存,以及把内存归还给后端。中端由Transfer cache和Central free list 组成。

    * Transfer Cache

    The transfer cache gets its name from situations where one thread is allocating memory that is deallocated by another thread. The transfer cache allows memory to rapidly flow between two different threads.
    If the transfer cache is unable to satisfy the memory request, or has insufficient space to hold the returned objects, it will access the central free list.

    * Central Free List

    The central free list manages memory in spans, a span is a collection of one or more  pages of memory. These terms will be explained in the next couple of sections.

    * Pagemap and Spans

    TCMalloc管理将堆(heap)分成pages, 在编译时设定pages大小。连续的pages 组成 Span对象。pagemap 用于查找span,或者定义特定对象的size-class。

    TCMalloc 采用2层(2-level) 或者3层(3-level)的radix tree 来映射spans定位的所有可能的内存。如下图Span A 拥有2pages, SpanB 拥有3pages。

    [pagemap.png]

    Spans 用于中端(middle-end)确定哪里存放返回的对象,以及在后端(back-end)管理page数组。

    * Storing Small Objects in Spans

    一个span包含一个指针,该指针指向TCMalloc pages的base; 对于small object,这些pages 被分解为2**16个对象。

     

    后端(Back-end)

    TCMalloc 能创建多种不同尺寸大小的 pages,TCMalloc page 大小有4KiB, 8KiB, 32KiB, and 256KiB.

    Consequently, it makes sense for applications with small memory footprints, or that are sensitive to memory footprint size to use smaller TCMalloc page sizes. Applications with large memory footprints are likely to benefit from larger TCMalloc page sizes.

    The back-end of TCMalloc has three jobs:

    • It manages large chunks of unused memory.
    • It is responsible for fetching memory from the OS when there is no suitably sized memory available to fulfill an allocation request.
    • It is responsible for returning unneeded memory back to the OS.

    There are two backends for TCMalloc:

    • The Legacy pageheap which manages memory in TCMalloc page sized chunks.
    • The hugepage aware pageheap which manages memory in chunks of hugepage sizes. Managing memory in hugepage chunks enables the allocator to improve application performance by reducing TLB misses.

    * Legacy Pageheap

    The legacy pageheap is an array of free lists for particular lengths of contiguous pages of available memory. For k < 256, the kth entry is a free list of runs that consist of k TCMalloc pages. The 256th entry is a free list of runs that have length >= 256 pages:

    [legacy pageheap]

    * Hugepage Aware Allocator

    The objective of the hugepage aware allocator is to hold memory in hugepage size chunks. On x86 a hugepage is 2MiB in size. To do this the back-end has three different caches:

     

     

     

     

     

     

     

     

     

     

     

     

    展开全文
  • Tcmalloc

    千次阅读 2019-02-22 11:33:47
    Tcmalloc Ptmalloc在性能上还是存在一些问题的,比如不同分配区(arena)的内存不能交替使用,比如每个内存块分配都要浪费8字节内存等等,所以一般倾向于使用第三方的malloc。 Tcmalloc是Google gperftools里的...

    Tcmalloc

    Ptmalloc在性能上还是存在一些问题的,比如不同分配区(arena)的内存不能交替使用,比如每个内存块分配都要浪费8字节内存等等,所以一般倾向于使用第三方的malloc。

    Tcmalloc是Google gperftools里的组件之一。全名是 thread cache malloc(线程缓存分配器)其内存管理分为线程内存中央堆两部分。

     

    小内存分配

    对于小块内存分配,其内部维护了60个不同大小的分配器(实际源码中看到的是86个),和ptmalloc不同的是,它的每个分配器的大小差是不同的,依此按8字节、16字节、32字节等间隔开。在内存分配的时候,会找到最小复合条件的,比如833字节到1024字节的内存分配请求都会分配一个1024大小的内存块。如果这些分配器的剩余内存不够了,会向中央堆申请一些内存,打碎以后填入对应分配器中。同样,如果中央堆也没内存了,就向中央内存分配器申请内存。

    在线程缓存内的60个分配器(_文档上说60个,但是我在2.0的代码里看到得是86个_)分别维护了一个大小固定的自由空间链表,直接由这些链表分配内存的时候是不加锁的。但是中央堆是所有线程共享的,在由其分配内存的时候会加自旋锁(spin lock)。

    在线程内存池每次从中央堆申请内存的时候,分配多少内存也直接影响分配性能。申请地太少会导致频繁访问中央堆,也就会频繁加锁,而申请地太多会导致内存浪费。在tcmalloc里,这个每次申请的内存量是动态调整的,调整方式使用了类似把tcp窗口反过来用的慢启动(slow start)算法调整max_length, 每次申请内存是申请max_length和每个分配器对应的num_objects_to_move中取小的值的个数的内存块。

    num_objects_to_move取值比较简单,是以64K为基准,并且最小不低于2,最大不高于32的值。也就是说,对于大于等于32K的分配器这个值为2(好像没有这样的分配器 class),对于小于2K的分配器,统一为32。其他的会把数据调整到64K / size 的个数。(可能是经验数值,目前2.0版本里的代码是这么写的)

    对于max_length就比较复杂了,而且其更多是用于释放内存。max_length由1开始,在其小于num_objects_to_move的时候每次累加1,大于等于的时候累加num_objects_to_move。释放内存的时候,首先max_length会对齐到num_objects_to_move,然后在大于num_objects_to_move的释放次数超过一定阀值,则会按num_objects_to_move缩减大小。

    大内存分配

    对于大内存分配(大于8个分页, 即32K),tcmalloc直接在中央堆里分配。中央堆的内存管理是以分页为单位的,同样按大小维护了256个空闲空间链表,前255个分别是1个分页、2个分页到255个分页的空闲空间,最后一个是更多分页的小的空间。这里的空间如果不够用,就会直接从系统申请了。

    分页管理 – span

    Tcmalloc使用一种叫span的东东来管理内存分页,一个span可以包含几个连续分页。一个span的状态只有未分配(这时候在空闲链表中),作为大对象分配,或作为小对象分配(这时候span内记录了小对象的class size)。

    在32位系统中,span分为两级由中央分配器管理。第一级有2^5个节点,第二级是2^15个。32位总共只能有2^20个分页(每个分页4KB = 2^12)。(骗纸,我在代码里明明看到的是2^7和2^13,定义了TCMALLOC_LARGE_PAGES宏之后才是 2^5和2^15,可是所有的代码或者编辑脚本里都没定义这个宏,可能是文档没更新)

    在64为系统中,有三级。

    资源释放的时候,首先计算其分页编号,然后再查找出它对应的span,如果它是一个小对象,则直接归入小对象分配器的空闲链表。等到空闲空间足够大以后划入中央堆。如果是大对象,则会把物理地址连续的前后的span也找出来,如果空闲则合并,并归入中央堆中。

    而线程缓存内的分配器,会根据max_length、num_objects_to_move和上一次垃圾收集到现在为止的最小链表长度,按一定的策略回收资源到中央堆中,具体的算法不再复述tcmalloc的文档写得比较清楚。同样可以在需要时减少某一个线程的max_length来转移内存,但是要等到那个线程下一次执行free,触发垃圾回收之后才会真正把内存返还中央堆。

    简而言之,就是:

    **小内存: 线程缓存队列 -> 中央堆 -> 中央页分配器(从系统分配)

    大内存: 中央堆 -> 向系统请求

    Tcmalloc的管理策略和ptmalloc有很大区别,理论上性能提高的主要原因在线程缓存不加锁和少量操作的自旋锁上。不过按照它的实现方式,不适合多线程频繁分配大于8个分页(32KB)的内存。否则自旋锁争用会相当厉害,不过这种情况也比较少。而减少和中央堆交互又依赖于他的线程缓存长度自适应算法。

    还有就是它使用了外部的数据结构来管理span list,这样不会每次分配内存都要浪费header的长度。但是他的对齐操作又比ptmalloc多浪费了一些内存。(有点空间换时间的意思)

    所以无论是ptmalloc还是tcmalloc都应该尽量减少大内存的分配和释放。尽量先分配、后释放。

     

    ptmalloc与tcmalloc的不足:

        都是针对小内存分配和管理;对大块内存还是直接用了系统调用。应该尽量避免大内存的malloc/new、free/delete操作。频繁分配小内存,例如:对bool、int、short进行new的时候,造成内存浪费。

    展开全文
  • tcmalloc

    2016-04-26 09:51:00
    引用链接:... TCMalloc:线程缓冲的Malloc:http://blog.csdn.net/chen19870707/article/details/40039401 使用TCMalloc的堆栈检查:http://blog.csdn.net/chen19870707/a...

    引用链接:http://blog.csdn.net/chen19870707/article/details/40301783

     

    TCMalloc:线程缓冲的Malloc:http://blog.csdn.net/chen19870707/article/details/40039401

    使用TCMalloc的堆栈检查:http://blog.csdn.net/chen19870707/article/details/40116379

    使用TCMalloc进行堆栈分析:http://blog.csdn.net/chen19870707/article/details/40145565

     

    glibc内存泄漏以及tcmalloc的简单分析:http://www.cnblogs.com/raymondshiquan/archive/2011/06/25/tcmalloc_configuration_analysis.html

     

    小记:http://blog.csdn.net/chosen0ne/article/details/9338591

    转载于:https://www.cnblogs.com/yangzhouyyz/p/5433863.html

    展开全文
  • tcmalloc-源码

    2021-02-23 03:44:38
    该存储库包含TCMalloc C ++代码。 TCMalloc是Google对C的malloc()和C ++的operator new的自定义实现,用于在C和C ++代码中进行内存分配。 TCMalloc是一种快速的多线程malloc实现。 构建TCMallocTCMalloc的官方...
  • tcmalloc浅析

    2021-02-19 13:31:06
    最近学习了tcmalloc机制,它是go里面用到的内存分配机制。本文参考tcmalloc,加上一部分自己的理解。 tcmalloc VS ptmalloc(glibc 2.3 malloc)   对于小内存来说,tcmalloc提供线程级别的内存分配,这样就减少了...

    最近学习了tcmalloc机制,它是go里面用到的内存分配机制。本文参考tcmalloc,加上一部分自己的理解。

    tcmalloc VS ptmalloc(glibc 2.3 malloc)

      对于小内存来说,tcmalloc提供线程级别的内存分配,这样就减少了线程之间的竞争,ptmalloc2也提供线程级别分配,但是它的内存被分配到某个线程后就不能重新分配给别的线程,这造成了较大的资源浪费。对于大内存来说,tcmalloc也采用了细粒度且高效的分配策略。
      在2.8 GHz P4环境下,tcmalloc执行小内存malloc/free的时间大约为50ns,小于ptmalloc2的300ns。
      另外在空间利用上,tcmalloc额外空间比较少,N个8字节的对象占用的总空间大概为8N*1.01,而ptmalloc2用4个字节管理每个对象,造成的空间利用率较小。

    小内存分配和回收

      线程维护了一个cache,用于小内存分配,当需要申请内存时,先从线程cache中进行分配,如果不够再从Central Heap的central free lists进行分配;此外,tcmalloc还会执行定期垃圾回收,将线程cache中过多的内存进行回收,放入central free lists中。
    1
      tcmalloc有大约88种大小的内存块(size-class),如果不足一块大小则会造成一定的碎片浪费,但是由于tcmalloc不是完全按2的指数倍进行分配的,所以浪费的空间不会很大。举个例子,内存块大小有8, 16, 32, 48, 64, 80,那么如果申请空间为70,分配块大小为80的即可,而不需要分配128造成较大的碎片浪费。所有的空闲块(class)以单链表进行维护,那么用到时直接从对应链表中取即可。
    2
    大体分配策略如下:

    1. 根据申请的大小,找到对应的块大小size-class。
    2. 如上图所示,从线程缓存链表中寻找对应块大小的空闲内存块
    3. 如果链表为非空,则直接返回,由于是线程内部没有竞争,所以不需要加锁。

    如果链表为空,则

    1. 从central free lists中找到对应size-class的链表空闲块(结构跟上图线程缓存中链表一致)
    2. 将从central free lists空闲链表中找到的空闲块放入到线程缓存的链表中
    3. 从线程缓存的链表中返回一个

    如果central free lists中对应size-class的链表也为空,则

    1. 则分配一个页
    2. 然后将该页划分出多个需要的size-class的块
    3. 将块放入central free lists空闲链表
    4. 将central free lists空闲链表空闲块一部分移入到线程缓存的链表中
    5. 从线程缓存的链表中返回一个

      这种多级分配的好处在于,第一级是线程内部资源,不需要进行加锁抢占影响性能。
      那么线程内部链表的长度到底应该为多少,如果小了将会导致不断从Central free list中进行申请,造成竞争;如果大了则会造成浪费。分配策略采取了慢启动增长的方式,防止系统因为大批量申请分配造成抖动,伪代码如下。

        Start each freelist max_length at 1.
        Allocation
      if freelist empty {
        fetch min(max_length, num_objects_to_move) from central list;
        if max_length < num_objects_to_move {  // slow-start, 每次只+1
          max_length++;
        } else { // 如果超过num_objects_to_move则快增长
          max_length += num_objects_to_move;
        }
      }
        Deallocation
      if length > max_length {
        // Don't try to release num_objects_to_move if we don't have that many.
        release min(max_length, num_objects_to_move) objects to central list
        if max_length < num_objects_to_move { // 尝试继续增长max_length长度
          // Slow-start up to num_objects_to_move.
          max_length++;
        } else if max_length > num_objects_to_move {
          // If we consistently go over max_length, shrink max_length. 计数策略,只有计数超过给定阈值,才会对max_length进行收缩,同样防止抖动。
              overages++;
          if overages > kMaxOverages {
            max_length -= num_objects_to_move;
            overages = 0;
          }
        }
      }
    

    中内存分配

      中内存指的是大小为256KB到1MB的大小,将会分配多个页,Central Heap以8k为一个页。Central Heap有一个包含128个链表的heap,链表大小从1个页到128个页。那么,如果申请的空间需要多少个page则从heap对应项中的链表中取出一个,如果该链表为空,则从下一个链表寻找(将会导致重新划分,比如需要4个页,但是4 pages链表为空,则从5pages中拿一个,但是5pages应该拆分为2部分,一个为4page,一个为1page)。如果都不满足需求,则视为“大内存”分配。
    3
      注意,中内存不是从线程缓存中分配,而是直接在CentralHeap。

    大内存分配

      大内存指的是大于1MB的块,这个将会从红黑树中进行分配。tcmalloc维护了一个红黑树用于标记不同的span,如果需要则从树种找到一个满足条件的最小的span进行分配。这可能导致span进行重新划分,一部分用于分配申请的大小,另外多出的部分可能重新放入到红黑树,也可能放入全局Centeral Heap的center free-lists(上图所示)。如果红黑树中找不到满足的span,则从系统中进行申请(tcmalloc采用sbrk和mmap)

    Span

      span对象负责管理连续的多个页,比如下图,a,b,c,d是4个span,管理不同大小的连续页。
    4
      所有span组成一个span lists,span内部划分给多个对象使用,参加下图,图来自图解 TCMalloc
    6
      一个span可能被分配或者释放。如果释放了,挂入到page heap的链表中。如果申请了,可能作为大内存被分配,也可能被划分后进行分配,比如划分为多个小内存。如果被划分成小内存,则内部会记录各个size-class的分配情况。
      同样还是上面第一个图,可以用一个数组记录各个页分别属于哪个span。但是这样对空间消耗比较大,每一块内存都需要一个数组元素表示,tcmalloc用基数radix tree(前缀树/字典树trie tree的一种压缩优化)记录映射情况,这样可以对前缀相同部分进行压缩。如果是32位系统,则树高2层,根节点包含了32项,叶子节点包含2^14项,则对32位系统来说,可以记录2^19个页(2^19 * 8k=2^32)。如下图所示,采用基数而不是前缀树的原因是为了空间压缩,如果是前缀树,则需要2^32 * 2 - 1=2^33-1个结点,就算结点内只有一个值和一个指针,存储这么多指针也需要浪费很多的空间。下图是手绘的radix tree示意图。
    5
      对于64位系统,则树高3层。

    回收

      当一个对象被释放后,通过计算页号,再通过radix tree得知所在的span,span可以知道是否为小内存,如果是的话还知道size-class(span内部维护该信息)。当然,在开始的时候说过,如果是小内存,释放会挂入线程内部的缓存链表,知道链表大小超过了阈值则会回收到central free lists。当然central free lists也可能发生回收,属于一个span的内存全部空闲后,将会触发回收。
      如果是大内存,则通过span获取页跨度,假设为[p,q],那么寻找p-1和q+1所在的span是否为空,如果都为空,则进行合并后放入page heap(上面提到的红黑树)。

    central free lists

      上面我们提过,我们在central free lists中保存了不同size-class小内存用于二次分配。每个central free lists由二级结构组成,第一级是span,第二级是span内空闲空间组成的链表,保存小内存地址。如果线程内部小内存不够用,就从这里进行分配。如果线程内部小内存过多就行回收,也挂入这里的链表。如果一个span内的内存全都回收后,该span也将进行回收,放入到全局的page heap中。

    线程缓存的垃圾回收

      在开始讲小内存的伪代码中已经介绍过垃圾回收的机制。当线程缓存超过max_size以后,将会触发回收。垃圾回收只有在对象释放的时候才会发生。用户可以通过控制tcmalloc_max_total_thread_cache_bytes来控制num_objects_to_move的大小。每次垃圾回收,线程将尝试将自己的max_size变大。如果回收时max_size小于tcmalloc_max_total_thread_cache_bytes,那么max_size将会直接增长;反之,则会促使从别的线程中偷取max_size。
    此处存在一个疑问:这种机制将会导致max_size超过tcmalloc_max_total_thread_cache_bytes,和上面伪代码中的收缩机制有什么区别?什么时候用收缩,什么时候从别的线程进行偷取?

    说明

    转载请注明链接:http://vinllen.com/tcmallocqian-xi/

    参考:

    https://gperftools.github.io/gperftools/tcmalloc.html
    https://github.com/gperftools/gperftools/blob/master/src/tcmalloc.cc
    https://zhuanlan.zhihu.com/p/29216091

    展开全文
  • Tcmalloc介绍

    2020-05-28 17:11:18
    tcmalloc 是Google推出的一种内存分配器,即线程缓存的malloc,实现了高效的多线程内存管理,用于替代系统的内存分配函数。 tcmalloc的内存分配策略 tcmalloc 分配的内存主要来自全局缓存堆和进程的私有缓存。小容量...
  • 图解 TCMalloc

    2020-10-29 23:55:18
    之所以学习 TCMalloc,是因为在学习 Golang 内存管理的时候,发现 Golang 竟然就用了鼎鼎大名的 TCMalloc,而在此之前虽然也对内存管理有过一些浅薄的了解,但一直没有机会深入。因此借此机会再巩.
  • TCMalloc 简介

    2020-06-14 09:21:52
    昨天聊的64MB内存中,有使用TCMalloc,但是对其原理不是很了解,所以学习了下。前言先不使用TCMalloc,先使用glibc自带的内存分配ptmalloc2进行内存分配,先看一个...
  • TCMalloc解密

    2019-09-13 19:06:44
    原文请移步我的博客:TCMalloc解密 写在前面 本文首先简单介绍TCMalloc及其使用方法,然后解释TCMalloc替代系统的内存分配函数的原理,然后从宏观上讨论其内存分配的策略,在此之后再深入讨论实现细节。 有几点...
  • tcmalloc 安装包

    2012-04-17 23:12:50
    These tools are for use by developers so that they can create more robust applications. Especially of use to those developing multi-... Includes TCMalloc, heap-checker, heap-profiler and cpu-profiler.
  • TCMalloc原理

    千次阅读 2016-02-17 12:05:40
    周末抽空看了一下tcmalloc,了解了个大概。下面记录一下。 一. 原理 tcmalloc就是一个内存分配器,管理堆内存,主要影响malloc和free,用于降低频繁分配、释放内存造成的性能损耗,并且有效地控制内存碎片。glibc中...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,069
精华内容 2,427
关键字:

tcmalloc