多個記憶體塊(Chunks)通常具有相同的尺寸,從記憶體塊邊界地址開始,多個領域( Arena)將眾多記憶體塊分割成較小的空間進行分配,超大的記憶體配置(huge arena)要同時佔據多個連續記憶體塊(Chunks)才夠用。
麥好的AI樂園部落格所有內容是原創,如果轉載請註明來源http://blog.csdn.net/myhaspl/
分配大小分為3個部分:小的、大的和巨大的,所有分配請求被安排到最接近的大小邊界,超大的記憶體配置大於記憶體塊的一半,這種分配儲存在單獨的紅/黑樹狀結構中。對小型和大型的分配,塊分割成頁,使用二夥伴(Binary-Buddy)演算法作為分割演算法,Binary-Buddy在分配記憶體的時候,首先找到一個空閑記憶體塊,接著把記憶體塊不斷的進行對半切分(切分得到的2個同樣大小的記憶體塊互為夥伴),直到切出來的記憶體塊剛好滿足分配需求為止,合并的時候,只有夥伴才能合并為一個新的記憶體塊。
小型和大型分配通過反覆將分配大小折半,最後走到一個記憶體頁,但只能合并的方式是分裂過程的相反操作,啟動並執行狀態資訊作為頁面映射儲存為每個記憶體塊(Chunks)的開始處,通過分開儲存這些資訊,頁面只接觸它們使用的部分,同時對於超過一半的頁,但沒有超過一半的記憶體塊的大型分配,這種做法同樣高效和安全。
小型分配分為三個類:小、量子尺寸(quantum-spaced)和子頁,根據資料類型的不同,現代架構要求記憶體對齊,malloc(3)要求返回適合邊界的記憶體時,在糟糕的情況下,對齊要求被稱為量子尺寸(通常是16位元組)。如所示:
jemalloc分配機制包括領域(arena)、塊(chunk)、執行(bin)、運行(run)、線程緩衝等部分,jemalloc使用多個分配領域(Arena)將記憶體分而治之,以塊(chunk)作為具體進行記憶體配置的地區,塊(chunk)以頁(page)為單位進行管理,每個塊(chunk)的前幾個 頁(page)用於儲存後面所有頁(page)的狀態,後面的所有頁(page)則用於進行實際的分配。執行(bin)用來管理各個不同大小單元的分配,每個執行(bin)通過對它對應的運行(run)操作來進行分配的,一個運行(run)實際上就是塊(chunk)裡的一塊地區 ,在分配記憶體時首先從線程對應的私人緩衝空間(tcache)中找。
但現代的處理器都是多處理器,並行計算已經慢慢成為一種趨勢,多線程運算不可避免,為提高malloc在多線程環境的效率和安全性,增強多線程的伸縮性,Jason Evans 在他的《A Scalable Concurrent malloc(3) Implementation for FreeBSD》一文中提出了並髮狀態的malloc機制,jemalloc使用多個分配領域(Arena)減少在多處理器系統中的線程之間的鎖競爭,雖然增加一些成本,但更有利於提供多線程的伸縮性。現代的多處理器在每個快取線(per-cache-line )的基礎上提供了記憶體的一致性視圖,如果兩個線程同時運行在不同的處理器上,但在同一緩衝線(cache-line)操縱不同的對象,那麼處理器必須仲裁緩衝線(cache-line)的所有權。
下面是jemalloc的核心層示意: