吃透Netty源碼系列二十九之池化內存分配總結

申請緩衝區

今天在來總結下內存分配中的幾個主要的角色。這個就是我們用的池化內存分配器,裏面會進行很多參數的配置,這些參數的默認值基本也是進行優化過的,如果需要特殊場景,可以進行參數調優,基本是這些參數:
在這裏插入圖片描述
這裏要知道,默認是初始化的時候是根據CPU個數*2的數量來進行arena的分區,也就是對應着默認事件循環的個數,每個事件循環會有一個線程,這樣避免線程間的競爭,當然如果有其他線程了,也會進行負載均衡的分配,儘可能避免多線程之間的競爭。
在這裏插入圖片描述

創建PoolThreadLocalCache

初始化的時候創建了PoolThreadLocalCache這個線程本地變量,使得每個線程都會有自己獨立的線程本地變量對應的值,這個值就是緩存PoolThreadCache
在這裏插入圖片描述

創建PoolThreadCache

然後又創建了PoolArena數組,再創建新的內存空間的時候會先從線程本地變量中獲取緩存,如果沒有創建緩存,就會進行initialValue初始化,根據PoolArena數組的使用情況,選取使用率最低的PoolArena來創建緩存PoolThreadCache並返回,當然這裏如果不使用緩存的話,裏面的屬性都是默認屬性。
在這裏插入圖片描述

獲取線程本地變量的PoolArena進行分配

然後在需要創建緩衝區的時候先獲取線程本地變量緩存中的PoolArena來分配。
在這裏插入圖片描述

嘗試用緩存來分配

當確定好緩衝區需要的容量後,如果容量小於塊大小的,先從嘗試從緩存中分配:
在這裏插入圖片描述
在這裏插入圖片描述
最終是將緩存中緩存的塊信息實體從隊列中取出來,重新初始化用。
在這裏插入圖片描述
說到底主要的還是塊和句柄,加起來就能定位到起始位置,就可以用了。
在這裏插入圖片描述

緩存分配失敗,走正常分配流程

當然如果緩存無法分配就走正常的分配流程,如果是tiny和small類型的,就進行子頁的分配,進行位圖的記錄,最後進行緩衝區的初始化:
在這裏插入圖片描述

釋放緩衝區

釋放緩衝區會將緩衝區的塊信息放進緩存裏,可以給下一個要申請同類型的尺寸的緩衝區。但是如果對應類型的緩衝區放滿了,或者沒有對應尺寸的緩衝區,那就直接釋放了,堆內存交給虛擬機,堆外就直接釋放內存。
在這裏插入圖片描述

創建實體放入隊列

放進緩衝區,就是把塊信息封裝成實體,然後放進隊列裏。
在這裏插入圖片描述

釋放塊

如果放不進緩存,那就會嘗試去釋放塊,如果塊的使用率是0了,那就會釋放內存。
在這裏插入圖片描述
釋放有子頁的:
在這裏插入圖片描述
真正銷燬塊:
在這裏插入圖片描述
在這裏插入圖片描述

防止內存泄露的措施

netty包裝後的任務都會有內存釋放,避免內存泄露。
在這裏插入圖片描述
對應到就是這裏:
在這裏插入圖片描述
在這裏插入圖片描述
其實大致上的流程還是簡單的,只是裏面的一些分配的小細節要花時間琢磨,比如夥伴算法分配和回收內存,比如位圖記錄子頁分配信息,如何使用內存映射索引和位圖信息來定位分配在塊中的起始位置。

好了,今天就到這裏了,希望對學習理解有幫助,大神看見勿噴,僅爲自己的學習理解,能力有限,請多包涵。

發佈了155 篇原創文章 · 獲贊 47 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章