歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Go語言內存分配器-FixAlloc

前面寫了一篇Go語言內存分配器設計,記錄了一下內存分配器的大體結構。在介紹內存分配器的核心實現前,本文先介紹一下內存分配器中一個工具組件——FixAlloc。FixAlloc稱不上是核心組件,只是輔助實現整個內存分配器核心的一個基礎工具罷了,由此可以看出FixAlloc還是一個比較重要的組件。引入FixAlloc的目的只是用來分配MCacheMSpan兩個特定的對象,所以內存分配器中有spanalloccachealloc兩個組件(見《Go語言內存分配器設計》的圖)。MCache和MSpan兩個結構在malloc.h中有定義。

定義在malloc.h文件中的FixAlloc結構如下,比較關鍵的三個字段是alloc、list和chunk,其他的字段主要都是用來統計一些狀態數據的,比如分配了多少內存之類。

struct FixAlloc
{
	uintptr size;
	void *(*alloc)(uintptr);
	void (*first)(void *arg, byte *p);	// called first time p is returned
	void *arg;
	MLink *list;
	byte *chunk;
	uint32 nchunk;
	uintptr inuse;	// in-use bytes now
	uintptr sys;	// bytes obtained from system
};

FixAlloc的內存結構圖,一看就很簡單,簡單到沒有出現本文的必要了。

list指針上掛的一個鏈表,這個鏈表的每個節點是一個固定大小的內存塊,cachealloc中的list存儲的內存塊大小為sizeof(MCache),而spanalloc中的list存儲的內存塊大小為sizeof(MSpan)chunk指針始終掛載的是一個128k大的內存塊。

FixAlloc提供了三個API,分別是runtime·FixAlloc_Init、runtime·FixAlloc_Alloc和runtime·FixAlloc_Free。

分配一個mcache和mspan的偽代碼:

MCache *mcache;
mcache = (MCache *) runtime·FixAlloc_Alloc(cachealloc);

MSpan *mspan;
mspan = (MSpan *) runtime·FixAlloc_Alloc(spanalloc);

這段偽代碼展示的是分配一個MCache和MSpan對象,內存分配器並不是直接使用malloc類函數向系統申請,而是走了FixAlloc。使用FixAlloc分配MCache和MSpan對象的時候,首先是查找FixAlloc的list鏈表,如果list不為空,就直接拿一個內存塊返回使用; 如果list為空,就把焦點轉移到chunk上去,如果128k的chunk內存中有足夠的空間,就切割一塊內存出來返回使用,如果chunk內存沒有剩余內存的話,就從操作系統再申請128k內存替代老的chunk。FixAlloc的固定對象分配邏輯就這麼簡單,相反釋放邏輯更簡單了,釋放的對象就是直接放到list中,並不會返回給操作系統。當然mcache的個數基本是穩定的,也就是底層線程個數,但span對象就不一定那麼穩定了,所以FixAlloc的內存可能增長的因素就是span的對象太多。

FixAlloc的實現位於mfixalloc.c文件中,代碼目前還不到100行,實在是太簡單了。本來是計劃本文一起介紹完FixAlloc和MSpan兩個基礎組件,今天身體不舒服,小感冒了,沒精力再寫MSpan了。

注:本文基於Go1.1.2版本。

Copyright © Linux教程網 All Rights Reserved