Netty內存池和對象池簡單總結

查閱的資料有限,歡迎糾錯

1 什麼是堆

JAVA中 調用new方法時候會堆上存放真正對象,棧中變量引用指向這個堆中的對象。

方法區改成元空間後,堆中也添加了常量池,因爲這個改變intern等也發生了變動

2 Netty下堆外內存和零拷貝是什麼

heapByteBuffer是 JVM 堆上分配byte的緩衝區
directByteBuffer 是不受 JVM 垃圾回收管理的堆外內存,通過類似對機器內存byte[]數組引用封裝,而不是傳輸拷貝數據實現的零拷貝

3 爲什麼需要堆外內存

1、減少垃圾回收次數
將大量網絡io讀寫數據請求的內存需求交給操作系統下堆外內存維護,這樣JVM中需要的堆內內存就維護很小,GC次數也會減少

2、提升IO拷貝效率 (類似零拷貝)

JVM管理的堆內內存屬於“用戶態”;操作系統管理的堆外內存屬於“內核態”。如果從堆內向磁盤寫數據時,數據會被先複製到堆外內存,即內核緩衝區,然後再由OS寫入磁盤,使用堆外內存避免了這個上下文開銷。

4 內存池相關問題簡單總結

1 爲什麼需要

創建堆外內存的速度比堆內存慢了10到20倍,爲了複用緩存,Netty就做了內存池,Netty的內存池是不依賴於JVM本身的GC的。內存池涉及堆外內存,操作系統層面,需要主動通知操作系統回收內存

2 如何實現
在PoolChunk中是完美二叉樹數據結構。二叉樹葉子節點爲2048個Page,每個Page的父節點用於分配pageSize*2大小內存。每個page就是分配的內存。然後以PoolChunkList鏈表形式將PoolChunk串聯起來。然後通過對象池具體存放內存池

3 如何回收內存池
使用了虛引用類似哨兵機制,通過引用計數算法,當引用計數爲0,則通知操作系統要回收了

5 對象池相關問題簡單總結

1 爲什麼需要

使得線程重複使用創建的對象,提高性能。包含了內存池中堆外內存和JVM中的堆內內存

2 如何實現

每個對象通過線程的ThreadLocal保存到自己線程的DefaultHandle數組中,並通過WeakOrderQueue將這些線程串聯起來。

pop方法:從ThreadLocal map<Stack<T>,WeakOrderQueue>下找到對象類型的queue,queue中每個節點也維護了一個線程變量,DefaultHandle存放真正對線的數組和WeakOrderQueue,通過線程變量判斷找到當前線程的節點,然後DefaultHandle數組中返回最後一個對象,如果數組size爲0則遍歷WeakOrderQueue來找到其他線程可能創建的對象

push方法:如果是當前線程則將對象放入數組末尾,滿了則擴容。如果不是當前線程則map中找到queue加入,如果找不到則創建一個新的
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章