首页 > 编程知识 正文

tcmalloc反而更慢,oracle数据库默认端口

时间:2023-05-06 00:06:14 阅读:168429 作者:1257

1. TCMalloc简介

2. 小对象分配

3. 中对象分配

4. 大对象分配

5. 总结

1. TCMalloc简介TCMalloc全名Thread-Caching Malloc,即线程缓存的malloc,提供了有效的多线程内存管理,并与系统内存分配相关的函数[malloc,线程缓存TCMalloc是gperftools的一部分,除TCMalloc外,gperftools还包括头检查器、头配置文件和CPU配置文件器。 本文仅讨论gperftools的TCMalloc部分。 TCMalloc是专门为多线程并发内存管理而设计的,TCMalloc主要在线程级别安装缓存,因此用户在请求内存时往往会进行未锁定的内存分配。 根据分配的内存大小,TCMalloc将内存分配分为以下三类:

简单介绍小对象分配、(0,256kb )中对象分配、(256 kb,1MB )大对象分配、(1MB,)几个概念。 Page,Span,PageHeap :

page :与操作系统管理内存的方式类似,TCMalloc将整个虚拟内存空间划分为大小相同的Page,每个page的默认值为8KB。 Span :将n个连续的page定义为一个http://www.Sina.com/page heap:TC malloc定义Span类来处理与向操作系统申请内存相关的操作,一层缓存PageHeap被认为是APP应用程序可以动态分配的整个内存的抽象。 PageHeap以span为单位向系统申请内存。 您申请的span可能只有一个page,也可能包含n个page。 它可以被分割成一系列小对象,用于分配小对象,也可以作为整体分配为中对象或大对象。

2 .小对象分配TCMalloc整体的小存储器(256k以下)的管理分别为ThreadCache )、Central Cache )、CentralFreeeList )、PageHeap )这3个阶段的缓存

2.1 size class相对于256KB以内的小客体,TCMalloc根据大小分为85种。 (虽然官方介绍说有88个左右,但我个人的实际测试是85个,不含0字节的大小)被称为PageHeap,各SizeClass分别对应一个大小。 例如,8当APP应用程序请求内存时,TCMalloc首先将请求的内存大小向上舍入到size class的大小。 例如,1到8个字节之间的内存申请分配8个字节,9到16个字节之间分配16个字节。 因此,会产生内部碎片。

2.2. ThreadCache对于每个线程,TCMalloc有另一个被称为Size Class的高速缓存。 这也是TCMalloc名字的由来(Thread-Caching Malloc )。 每个ThreadCache为每个size class都有一个单独的ThreadCache,用于缓存n个尚未在APP应用程序中使用的空闲对象。 小对象的分配直接从ThreadCache的FreeList返回空对象,相应地小对象的回收也返回到ThreadCache的对应的FreeList。 每个线程都有一个ThreadCache,因此从ThreadCache中加载和回收内存的速度很快,速度为FreeList。 为了便于汇总数据,每个线程的ThreadCache都连接到双向链表。 ThreadCache的结构大致如下所示。

2.3 .在central cache中,ThreadCache的空闲对象来自哪里? 答案是不需要加锁——所有线程的公共高速缓存。 与ThreadCache一样,CentralCache中也针对每个size class,输入CentralCache

>,供各线程的ThreadCache从中取用空闲对象。由于是所有线程公用的,因此从CentralCache中取用或回收对象,是需要加锁的。为了平摊锁操作的开销,ThreadCache一般从CentralCache中一次性取用或回收多个空闲对象。CentralCache在TCMalloc中并不是一个类,只是一个逻辑上的概念,其本质是CentralFreeList类型的数组。后文会详细讨论CentralCache的内部结构,现在暂且认为CentralCache的简化结构如下:

                   

2.4. PageHeap

    CentralCache中的空闲对象又是从何而来呢?答案是之前提到的PageHeap——TCMalloc对可动态分配的内存的抽象。当CentralCache中的空闲对象不够用时,CentralCache会向PageHeap申请一块内存(可能来自PageHeap的缓存,也可能向系统申请新的内存),并将其拆分成一系列空闲对象,添加到对应size class的CentralFreeList中。PageHeap内部根据内存块(span)的大小采取了两种不同的缓存策略。128个page以内的span,每个大小都用一个链表来缓存,超过128个page的span,存储于一个有序set(std::set)。讨论TCMalloc的实现细节时再具体分析,现在可以认为PageHeap的简化结构如下:

        

2.5 内存回收

    上面说的都是内存分配,内存回收的情况是怎样的?应用程序调用free()或delete一个小对象时,仅仅是将其插入到ThreadCache中其size class对应的FreeList中而已,不需要加锁,因此速度也是非常快的。只有当满足一定的条件时,ThreadCache中的空闲对象才会重新放回CentralCache中,以供其他线程取用。同样的,当满足一定条件时,CentralCache中的空闲对象也会还给PageHeap,PageHeap再还给系统。

2.6 小结

    总结一下,小对象分配流程大致如下:

将要分配的内存大小映射到对应的size class。查看ThreadCache中该size class对应的FreeList。如果FreeList非空,则移除FreeList的第一个空闲对象并将其返回,分配结束。如果FreeList是空的: 从CentralCache中size class对应的CentralFreeList获取一堆空闲对象。 如果CentralFreeList也是空的,则: 向PageHeap申请一个span。拆分成size class对应大小的空闲对象,放入CentralFreeList中。 将这堆对象放置到ThreadCache中size class对应的FreeList中(第一个对象除外)。返回从CentralCache获取的第一个对象,分配结束。3. 中对象分配

    超过256KB但不超过1MB(128个page)的内存分配被认为是中对象分配,采取了与小对象不同的分配策略。首先,TCMalloc会将应用程序所要申请的内存大小向上取整到整数个page(因此,这里会产生1B~8KB的内部碎片)。之后的操作表面上非常简单,向PageHeap申请一个指定page数量的span并返回其起始地址即可。

    对128个page以内的span和超过128个page的span,PageHeap采取的缓存策略不一样。为了描述方便,以下将128个page以内的span称为专一的手机,大于128个page的span称为xxdlz。先来看专一的手机是如何管理的,xxdlz的管理放在大对象分配一节介绍。PageHeap中有128个专一的手机的链表,分别对应1~128个page的span:

    

    假设要分配一块内存,其大小经过向上取整之后对应k个page,因此需要从PageHeap取一个大小为k个page的span,过程如下:

从k个page的span链表开始,到128个page的span链表,按顺序找到第一个非空链表。取出这个非空链表中的一个span,假设有n个page,将这个span拆分成两个span: 一个span大小为k个page,作为分配结果返回。另一个span大小为n – k个page,重新插入到n – k个page的span链表中。如果找不到非空链表,则将这次分配看做是大对象分配4. 大对象分配

    超过1MB(128个page)的内存分配被认为是大对象分配,与中对象分配类似,也是先将所要分配的内存大小向上取整到整数个page,假设是k个page,然后向PageHeap申请一个k个page大小的span。对于中对象的分配,如果上述的span链表无法满足,也会被当做是大对象来处理。也就是说,TCMalloc在源码层面其实并没有区分中对象和大对象,只是对于不同大小的span的缓存方式不一样罢了。大对象分配用到的span都是超过128个page的span,其缓存方式不是链表,而是一个按span大小排序的有序set(std::set),以便按大小进行搜索。

    假设要分配一块超过1MB的内存,其大小经过向上取整之后对应k个page(k>128),或者是要分配一块1MB以内的内存,但无法由中对象分配逻辑来满足,此时k <= 128。不管哪种情况,都是要从PageHeap的span set中取一个大小为k个page的span,其过程如下:

搜索set,找到不小于k个page的最小的span(best-fit),假设该span有n个page。将这个span拆分为两个span: 一个span大小为k个page,作为结果返回。另一个span大小为n – k个page,如果n – k > 128,则将其插入到xxdlz的set中,否则,将其插入到对应的专一的手机链表中。如果找不到合适的span,则使用sbrk或mmap向系统申请新的内存以生成新的span,并重新执行中对象或大对象的分配算法。5. 总结

    画张图概括下TCMalloc的管理内存的策略:

    不超过256KB的小对象分配,在应用程序和内存之间其实有三层缓存:PageHeap、CentralCache、ThreadCache。而中对象和大对象分配,则只有PageHeap一层缓存。

参考:https://wallenwang.com/2018/11/tcmalloc/

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。