TCMalloc 內存分配原理簡析
- 2020 年 10 月 24 日
- 筆記
- [01-1]深入理解golang, [01]Go, [05]linux內核-網絡, Go, 內存, 原理
一、TCMalloc
TCMalloc簡介
為啥要介紹 TCMalloc?
因為golang的內存分配算法絕大部分都是來自 TCMalloc,golang只改動了其中的一小部分。所以要理解golang內存分配算法,就要先了解下TCMalloc,為後面分析golang內存做一做功課。
tcmalloc 是google開發的內存分配算法庫,最開始它是作為google的一個性能工具庫 perftools 的一部分。TCMalloc是用來替代傳統的malloc內存分配函數。它有減少內存碎片,適用於多核,更好的並行性支持等特性。
前面TC就是Thread Cache兩英文的簡寫。
它提供了很多優化,如:
- TCMalloc用固定大小的page(頁)來執行內存獲取、分配等操作。這個特性跟Linux物理內存頁的劃分是不是有同樣的道理。
- TCMalloc用固定大小的對象,比如8KB,16KB 等用於特定大小對象的內存分配,這對於內存獲取或釋放等操作都帶來了簡化的作用。
- TCMalloc還利用緩存常用對象來提高獲取內存的速度。
- TCMalloc還可以基於每個線程或者每個CPU來設置緩存大小,這是默認設置。
- TCMalloc基於每個線程獨立設置緩存分配策略,減少了多線程之間鎖的競爭。
TCMalloc架構簡圖
-
Front-end:
它是一個內存緩存,提供了快速分配和重分配內存給應用的功能。它主要有2部分組成:Per-thread cache 和 Per-CPU cache。 -
Middle-end:
職責是給Front-end提供緩存。也就是說當Front-end緩存內存不夠用時,從Middle-end申請內存。它主要是 Central free list 這部分內容。 -
Back-end:
這一塊是負責從操作系統獲取內存,並給Middle-end提供緩存使用。它主要涉及 Page Heap 內容。
TCMalloc將整個虛擬內存空間劃分為n個同等大小的Page。將n個連續的page連接在一起組成一個Span。
PageHeap向OS申請內存,申請的span可能只有一個page,也可能有n個page。
ThreadCache內存不夠用會向CentralCache申請,CentralCache內存不夠用時會向PageHeap申請,PageHeap不夠用就會向OS操作系統申請。
小對象內存分配 ThreadCache
TCMalloc 定義了很多個size class,每個size class都維護了一個可分配的的空閑列表,空閑列表中的每一項稱為一個object(如下圖),同一個size-class的空閑列表中每個object大小相同。
在申請小內存時(小於256K),TCMalloc會根據申請內存大小映射到某個size-class中。
比如,申請0到8個位元組的大小時,會被映射到size-class1中,分配8個位元組大小;申請9到16位元組大小時,會被映射到size-class2中,分配16個位元組大小….以此類推。
上面每一個object都是 N bytes。用於Thread Cache小內存分配。
這個就組成了每一個ThreadCache的free list,thread可以從各自的free list獲取對象,不需要加鎖,所以速度很快。
如果ThreadCache的free list為空呢?那就從CentralCache中的CentralFreeList中獲取若干個object到ThreadCache對應的size class列表中,然後在取出其中一個object返回。
如果CentralFreeList中的object不夠用了呢?那CentralFreeList就會向PageHeap申請一連串由Span組成頁面,並將申請的頁面切割成一系列的object之後,再將部分object轉移給ThreadCache。
如果PageHeap也不夠用了呢?那就向OS操作系統申請內存。
從上面論述可以看出,這也是一個多級緩存思想的應用。
當申請的內存大於256K時,不在通過ThreadCache分配,而是通過PageHeap直接分配大內存。
大對象內存分配 PageHeap
PageHeap負責向操作系統申請內存。
tcmalloc也是基於頁的分配方式,即每次申請至少一頁(page)的內存大小。tcmalloc中一頁大小為8KB,多數linux中一頁為4KB,tcmallo的一頁是linux一頁大小的2倍。
PageHeap申請內存時按照頁申請,但它管理分配好的page內存時的基本單位是Span,Span對象代表了連續的頁。如下圖所示:
PageHeap中是如何組織Span,如下圖
Middle end-Central Free List
CentralFreeList的作用就是從PageHeap中取出部分Span,然後按照預定大小將其拆分成固定大小的object,提供給ThreadCache使用。
[完]
二、參考
- TCMalloc
- TCMalloc Design
- TCMalloc : Thread-Caching Malloc
- google gperftools
- 圖解TCMalloc
- TCMalloc的工作原理