1. 程式人生 > >netty 原始碼解讀三 記憶體分配相關(1)-buddy 夥伴記憶體分配演算法

netty 原始碼解讀三 記憶體分配相關(1)-buddy 夥伴記憶體分配演算法

1.前言:

PooledByteBufAllocator 實現相當複雜,其中涉及許多複雜的資料結構類:

1)PoolArena

2)PoolChunk 

3)PoolSubpage

5)PoolThreadCache

還有其他相關輔助類包括 PoolChunkList

其核心思想是利用了為 FreeBSD 設計的 jemalloc 記憶體分配演算法和 buddy  分配演算法。為了更好地解讀 netty 記憶體分配,本節首先著重介紹 buddy  分配演算法。

2.演算法

記憶體管理,特別是記憶體分配一直是作業系統一個基本問題。固定的劃分模式會限制活躍程序的數量,而且如果程序請求的大小與可用的分割大小匹配效果不佳,會導致記憶體空間的使用效率很低。動態劃分模式使得維護更復雜,包括記憶體合併的開銷。而夥伴演算法就是權衡折中的一種演算法。最早由貝爾電話實驗室的 Ken C Knowlton 在1965年的

《A fast storage allocator》一文中提出。

在夥伴演算法中,把用來分配的記憶體作為一整塊2次冪大小的空間。當請求到達時,如果請求的大小大於初始大小空間的一半,那麼整塊記憶體都會被分配。否則,這個記憶體塊會一分為二(這兩塊記憶體塊互為夥伴,演算法名即來源於此),這時候再一次判斷請求的大小是否大於其中一塊子記憶體塊的一半,如果大於,則這塊子塊將被分配。如果小於,那麼再將其中一個子塊一分為二,以此類推,直到請求的大小大於分割後的子塊的一半,若未找到,則直到分割系統允許的最小單位為止,然後再將相應記憶體塊分配。

在此演算法中,當一個程序結束時,分配給程序的記憶體塊會被釋放。只要有可能,一個未分配的記憶體塊就會試圖與其夥伴塊合併以便形成一個更大的空閒記憶體塊。如果兩個記憶體塊是由同一個父記憶體塊一分為二產生的,那麼他們就互為夥伴。

下面的例子展示了夥伴演算法的具體分配過程。假設初始記憶體塊大小為1024KB,表左側為程序每次請求的記憶體大小。

分配時優先考慮從低地址開始適配記憶體塊。