STL memory pool的詳細解析下

2021-07-06 09:49:06 字數 3252 閱讀 6329

首先需要把你的需要取得記憶體塊轉換成8的倍數這樣轉換 (m+ 8 - 1)&~(8-1)這樣的話就可以轉化了,

然後直接找打自由鍊錶的節點需要這個函式freelist_index這個函式可以計算你的第幾個自由鍊錶;

然後直接找到自由鍊錶中的現在可以使用的頭結點的位址這裡用my_free_list = freelist + index;

然後找到之後就開始分配了,看看你的自由聯是不是還有可以分配的記憶體,

如果有就直接移動你的freelist中儲存的可以分配的該自由鍊錶的位址的資訊,就是這樣操作

object* volatile* my_free_list = freelist + index(n);

object* result = *my_free_list;

*my_free_list = result->next;

return result;這裡就直接返回了result了;

這裡有乙個我必須得說;

就是object這個union,這個union使用的是union object

這裡使用union是有用意的;

這個union在後端的話用的是union中的object*next,而在客端用的是client_data[0];

注意到這裡union的size只有4bytes

注意這個union可以說同一時間只有乙個東西,但是最厲害的就是這個東西是個指標;

真是太聰明的設計,很細節的東西,雖然只節省了4byte這裡是32位機;

現在繼續說上面的result如果返回的是0的話說明你的自由鍊錶已經用完了所有的chunk,那麼現在需要的就是重新申請乙個chunk

但是chunk_alloc中申請的只是你的需要的記憶體然後並沒有加入你的自由鍊錶中;而如果需要加入到自由鍊錶中就需要這個函式refill這個函式;

先說一下chunk_alloc這個函式其實我感覺memory pool裡面最核心的**就是chunk_alloc了

首先這個你申請的為 size_t m 然後記憶體池裡面的start_free 和end_free這兩個變數很好理解;自由區鍊錶的記憶體都是來自於記憶體池;而記憶體池就需要start_free和end_free這兩個東西表示剩下的bytes很好理解;

然後bytes_left =  end_free - start_free;然後就得到了byte_left剩下的bytes了,然後比較bytes_left和m*20的大小;如果bytes_left > m*20說明你的剩下的足夠分配了;但是這裡還得說一下就是這個m*20這個為啥是個20呢,因為這裡需要一次效能多分配就多分配;下一次就不用分配了;減少了時間複雜度吧;

然後還有一種情況就是你分配的剛好只能分配乙個以上的chunk的大小;說到這裡就有乙個東西需要注意乙個引數很重要就是int& node 注意這裡是reference這裡的node的使用是說明你申請的chunk的塊數,但是在refill呼叫chunk_alloc的時候預設設定為20了,剛才為啥是20,原因就在這裡了;

現在呢不夠申請20個chunk了,那就能申請幾個就申請幾個唄;

node = bytes_left / m;

total_bytes = node * m;

result = start_free;

start_free += total_types;

return result;

這裡就返回了乙個以上少於20個chunk;

但是還有就是乙個都不夠呢;這裡的設計也是很聰明的;

就是先掃一下start_free到end_free還剩多少還夠給哪個自由鍊錶新增chunk,然後找到那個freelist+n然後直接在前面把這個;記憶體塊載入進這個自由鍊錶;

這裡的m都是已經8的倍數化了啊!

當然現在就是你的需要做的就是尋找你的m的倍數的chunk,找到如果m倍數的chunk存在的話,直接把他拿到記憶體池裡面來;

for(;m < max_size;m+=align)

} 然後是山窮水盡實在沒有了自由鍊錶中也找不到了這裡就給記憶體池分配一片空間;

但是這個空間是size_t bytes = 2 * total_sizes + (heap_size >>4)這裡我有個問題就是這個heap_size真的有用處嗎;

還不如size_t bytes = 3 * total_sizes;直接申請3個;

這裡直接給記憶體池擴增為你的需求的2倍,可見記憶體的增長幅度也不是很大;

void* p  = malloc(bytes);

if(p)

這裡還有一種情況就是如果沒有申請到呢;

先把end_free = 0;end_free置為0再說;

然後利用一級記憶體池配置器配置

start_free = __malloc_alloc_template::allocate(bytes);

這裡每次如果記憶體池有乙個不夠就儲存當前需要的記憶體池的大小這裡就是bytes heap_sizes = bytes;

end_free =  start_free + bytes;

然後chunk_alloc();遞迴呼叫chunk_alloc直接分配記憶體;

char* __default_alloc_template::chunk_alloc(size_t n, int& node)

else if (end_storage >= n)

else

size_t get_bytes = 2 * total_alloc + round_up(heap_size >> 4);

start_free = static_cast(malloc(get_bytes));

object* p = nullptr;

if (start_free == null)

}end_free = 0;

start_free = static_cast(malloc_alloc::allocate(get_bytes));

} heap_size += get_bytes;

end_free = start_free + get_bytes;

return chunk_alloc(n, node);

}}

templatevoid* __default_alloc_template::refill(size_t n)

else

else

} }return (void*)(result);

}

看完了 我只想說一句話 ,真是stl的這個記憶體池真的很精髓,我基本上該分析的東西基本都分析到了,如果那裡不懂的,可以隨時向我提問;我樂意解答,只要我能幫到的;

postman Variables變數的詳解與應用

全域性變數 集合變數 自定義環境變數 資料變數 本地變數 可以通過 的方式使用變數,如下圖所示 postman在請求構造器的右上角提供了兩處比較便捷的方式設定全域性變數和自定義環境變數,分別是環境快速預覽按鈕和環境設定按鈕。如下圖所示 環境快速預覽頁面 環境設定頁面 全域性變數儲存在postman的...

tomcate 的 server xml元素詳解

元素名 屬性 解釋 server port 指定乙個埠,這個埠負責監聽關閉 tomcat 的請求 shutdown 指定向埠傳送的命令字串 service name 指定 service 的名字 connector 表示客戶端和 service 之間的連線 port 指定伺服器端要建立的埠號,並在這...

ImageMagick的linux安裝詳解

imagemagick的linux安裝詳解 系統版本 rhel 4u4 freetype 2.1.9 1.i386.rpm 吧這個包裝上。我的系統安裝文件上預設就少這個包 在cd2裡 開啟控制台,切換到剛剛解壓出來的imagemagick的目錄。執行下列命令 1 configure enable s...