深入淺出Netty內存管理 PoolChunkList

前面兩篇分別分析了PoolChunk和PoolSubpage的實現,本文主要分析管理PoolChunk生命周期的PoolChunkList。
1、深入淺出Netty內存管理 PoolChunk
2、深入淺出Netty內存管理 PoolSubpage

PoolChunkList

PoolChunkList負責管理多個chunk的生命周期,在此基礎上對內存分配進行進一步的優化。

final class PoolChunkList<T> implements PoolChunkListMetric {
    
    private final PoolChunkList<T> nextList;
    private final int minUsage;
    private final int maxUsage;

    private PoolChunk<T> head;
    private PoolChunkList<T> prevList;
    ...
}

從代碼實現可以看出,每個PoolChunkList實例維護了一個PoolChunk鏈表,自身也形成一個鏈表,為何要這么實現?

Paste_Image.png

隨著chunk中page的不斷分配和釋放,會導致很多碎片內存段,大大增加了之后分配一段連續內存的失敗率,針對這種情況,可以把內存使用率較大的chunk放到PoolChunkList鏈表更后面,具體實現如下:

boolean allocate(PooledByteBuf<T> buf, int reqCapacity, int normCapacity) {
    if (head == null) {
        return false;
    }

    for (PoolChunk<T> cur = head;;) {
        long handle = cur.allocate(normCapacity);
        if (handle < 0) {
            cur = cur.next;
            if (cur == null) {
                return false;
            }
        } else {
            cur.initBuf(buf, handle, reqCapacity);
            if (cur.usage() >= maxUsage) {   // (1)
                remove(cur);
                nextList.add(cur);
            }
            return true;
        }
    }
}

假設poolChunkList中已經存在多個chunk。當分配完內存后,如果當前chunk的使用量超過maxUsage,則把該chunk從當前鏈表中刪除,添加到下一個鏈表中。

但是,隨便chunk中內存的釋放,其內存使用率也會隨著下降,當下降到minUsage時,該chunk會移動到前一個列表中,實現如下:

boolean free(PoolChunk<T> chunk, long handle) {
    chunk.free(handle);
    if (chunk.usage() < minUsage) {
        remove(chunk);
        if (prevList == null) {
            assert chunk.usage() == 0;
            return false;
        } else {
            prevList.add(chunk);
            return true;
        }
    }
    return true;
}

從poolChunkList的實現可以看出,每個chunkList的都有一個上下限:minUsage和maxUsage,兩個相鄰的chunkList,前一個的maxUsage和后一個的minUsage必須有一段交叉值進行緩沖,否則會出現某個chunk的usage處于臨界值,而導致不停的在兩個chunk間移動。

所以chunk的生命周期不會固定在某個chunkList中,隨著內存的分配和釋放,根據當前的內存使用率,在chunkList鏈表中前后移動。

END。
我是占小狼。
在魔都艱苦奮斗,白天是上班族,晚上是知識服務工作者。
如果讀完覺得有收獲的話,記得關注和點贊哦。
非要打賞的話,我也是不會拒絕的。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 前面分別分析了PoolChunk、PoolSubpage和PoolChunkList,本文主要分析PoolAren...
    美團Java閱讀 16,372評論 1 20
  • Netty中有一個主要的特點,就是ByteBuf的實現, 由于NIO中java.nio.ByteBuf中只有pos...
    橋頭橋尾閱讀 1,135評論 0 2
  • 概述 我們都知道一個進程是與其他進程共享CPU和內存資源的。正因如此,操作系統需要有一套完善的內存管理機制才能防止...
    SylvanasSun閱讀 3,887評論 0 25
  • 一氣呵成將余華的《活著》看完了。當一個人的命運、故事,讓我用旁人的眼光將它迅速看完時,心情是那樣沉重。合上書,眼前...
    沐伊520閱讀 512評論 0 1
  • 寫給你懂我 懶得去寫什么 我懶得去懂我 像你一樣 憂傷是心里的主調 帶著纏綿的燈光一樣懶 你說我消極 好像 是懶得...
    青早閱讀 240評論 0 0