SGI STL的內(nèi)存池
stl中各種容器都有一個(gè)可選的模板參數(shù):allocator,也就是一個(gè)負(fù)責(zé)內(nèi)存分配的組件。STL標(biāo)準(zhǔn)規(guī)定的allcator
被定義在memory文件中。STL標(biāo)準(zhǔn)規(guī)定的allocator只是單純地封裝operator new,效率上有點(diǎn)過(guò)意不去。
SGI實(shí)現(xiàn)的STL里,所有的容器都使用SGI自己定義的allocator。這個(gè)allocator實(shí)現(xiàn)了一個(gè)small object的內(nèi)存池。
Loki里為了處理小對(duì)象的內(nèi)存分配,也實(shí)現(xiàn)了類似的內(nèi)存管理機(jī)制。
該內(nèi)存池大致上,就是一大塊一大塊地從系統(tǒng)獲取內(nèi)存,然后將其分成很多小塊以鏈表的形式鏈接起來(lái)。其內(nèi)部
有很多不同類型的鏈表,不同的鏈表維護(hù)不同大小的內(nèi)存塊。每一次客戶端要求分配內(nèi)存時(shí),allcator就根據(jù)請(qǐng)求
的大小找到相應(yīng)的鏈表(最接近的尺寸),然后從鏈表里取出內(nèi)存。當(dāng)客戶端歸還內(nèi)存時(shí),allocator就將這塊內(nèi)存
放回到對(duì)應(yīng)的鏈表里。
我簡(jiǎn)單地畫了幅圖表示整個(gè)結(jié)構(gòu):
allocator內(nèi)部維護(hù)一個(gè)鏈表數(shù)組,數(shù)組元素全部是鏈表頭指針。鏈表A每一個(gè)節(jié)點(diǎn)維護(hù)一個(gè)8bytes的內(nèi)存塊,鏈表
B每一個(gè)節(jié)點(diǎn)維護(hù)一個(gè)16bytes的內(nèi)存塊。
當(dāng)客戶端請(qǐng)求分配10bytes的內(nèi)存時(shí),allocator將10調(diào)整為最接近的16bytes(只能大于10bytes),然后發(fā)現(xiàn)16bytes
這個(gè)鏈表(鏈表B)里有可用內(nèi)存塊,于是從B里取出一塊內(nèi)存返回。當(dāng)客戶端歸還時(shí),allocator找到對(duì)應(yīng)的鏈表,將
內(nèi)存重新放回鏈表B即可。
大致過(guò)程就這么簡(jiǎn)單,也許有人要說(shuō)用鏈表維護(hù)一塊內(nèi)存,鏈表本身就會(huì)浪費(fèi)一些內(nèi)存(在我很早前接觸內(nèi)存池時(shí),
總會(huì)看到類似的論點(diǎn)= =|),其實(shí)通過(guò)一些簡(jiǎn)單的技巧是完全可以避免的。例如,這里allocator維護(hù)了很多內(nèi)存塊,
反正這些內(nèi)存本身就是閑置的,因此我們就可以直接在這些內(nèi)存里記錄鏈表的信息(下一個(gè)元素)。
還是寫點(diǎn)代碼詳細(xì)說(shuō)下這個(gè)小技巧:
struct Obj
{
Obj *next;
}; 
void *mem = malloc( 100 );
Obj *header = (Obj*) mem;
Obj *cur_obj = header;
Obj *next_obj = cur_obj;
for( int i = 0; ; ++ i )
{
cur_obj = next_obj;
next_obj = (Obj*)((char*)next_obj + 10 );
if( i == 9 )
{
cur_obj->next = 0;
break;
}
else
{
cur_obj->next = next_obj;
}
}
free( mem );
這樣,通過(guò)header指針和next域,就可以逐塊(這里是10byts)地訪問(wèn)mem所指向的內(nèi)存,而這些鏈表的節(jié)點(diǎn),都
是直接保存在這塊內(nèi)存里的,所以完全沒(méi)有額外消耗。
我用C模仿著SGI的這個(gè)allocator寫了個(gè)可配置的內(nèi)存池,在其上按照STL的標(biāo)準(zhǔn)包裝了一個(gè)allocator,可以直接
用于VC自帶的STL里。測(cè)試代碼稍微測(cè)試了下,發(fā)現(xiàn)在不同的機(jī)器上有明顯的差距。
posted on 2008-06-12 21:26 Kevin Lynx 閱讀(8062) 評(píng)論(10) 編輯 收藏 引用 所屬分類: c/c++ 、game develop 、通用編程

