PoolChunkList

概要

在Netty中, PoolArena將內(nèi)存分為很多PoolChunk進行管理. 通過多個PoolChunkList根據(jù)PoolChunk的使用率進行分組保存唠粥,并將動態(tài)的移動至對應的PoolChunkList中

在PoolArena中根據(jù)使用率分如下幾組PoolChunkList

private final PoolChunkList<T> q050; //存儲內(nèi)存利用率50-100%的PoolChunk
private final PoolChunkList<T> q025; //存儲內(nèi)存利用率25-75%的PoolChunk
private final PoolChunkList<T> q000; //存儲內(nèi)存利用率1-50%的PoolChunk
private final PoolChunkList<T> qInit; //存儲內(nèi)存利用率0-25%的PoolChunk
private final PoolChunkList<T> q075; //存儲內(nèi)存利用率75-100%的PoolChunk
private final PoolChunkList<T> q100; //存儲內(nèi)存利用率100%的PoolChunk

q100 = new PoolChunkList<T>(null, 100, Integer.MAX_VALUE, chunkSize);
q075 = new PoolChunkList<T>(q100, 75, 100, chunkSize);
q050 = new PoolChunkList<T>(q075, 50, 100, chunkSize);
q025 = new PoolChunkList<T>(q050, 25, 75, chunkSize);
q000 = new PoolChunkList<T>(q025, 1, 50, chunkSize);
qInit = new PoolChunkList<T>(q000, Integer.MIN_VALUE, 25, chunkSize);

q100.prevList(q075);
q075.prevList(q050);
q050.prevList(q025);
q025.prevList(q000);
q000.prevList(null);
qInit.prevList(qInit);
img

PoolChunkList類主要屬性如下所示:

// 下一個ChunkList
private final PoolChunkList<T> nextList;
// 最小內(nèi)存使用率
private final int minUsage;
// 最大內(nèi)存使用率
private final int maxUsage;
private final int maxCapacity;
// 頭節(jié)點
private PoolChunk<T> head;
// 上一個ChunkList
private PoolChunkList<T> prevList;
img

構(gòu)造方法

PoolChunkList(PoolChunkList<T> nextList, int minUsage, int maxUsage, int chunkSize) {
    assert minUsage <= maxUsage;
    this.nextList = nextList;
    this.minUsage = minUsage;
    this.maxUsage = maxUsage;
    // 該list所能分配的最大容量
    maxCapacity = calculateMaxCapacity(minUsage, chunkSize);
}

private static int calculateMaxCapacity(int minUsage, int chunkSize) {
    minUsage = minUsage0(minUsage);

    if (minUsage == 100) {
        return 0;
    }
    // 計算一個chunk在除去最小的使用率的情況下所能分配的最大空間
    // Q25的maxCapacity=chunkSize*75%
    return  (int) (chunkSize * (100L - minUsage) / 100L);
}

添加

void add(PoolChunk<T> chunk) {
    // 看當前chunk的使用率是否超過了最大值, 加到下一個list
    if (chunk.usage() >= maxUsage) {
        nextList.add(chunk);
        return;
    }
    add0(chunk);
}

void add0(PoolChunk<T> chunk) {
    // 在chunk中保存所屬的chunlist
    chunk.parent = this;
    // 如果還沒有head, chunk來
    if (head == null) {
        head = chunk;
        chunk.prev = null;
        chunk.next = null;
    } else {
        // 將這個chunk加到list里面作為新的head
        chunk.prev = null;
        chunk.next = head;
        head.prev = chunk;
        head = chunk;
    }
}

刪除

private void remove(PoolChunk<T> cur) {
    if (cur == head) {
        // 讓下一個接替head
        head = cur.next;
        if (head != null) {
            head.prev = null;
        }
    } else {
        // 將cur前后解綁
        PoolChunk<T> next = cur.next;
        cur.prev.next = next;
        if (next != null) {
            next.prev = cur.prev;
        }
    }
}

分配

boolean allocate(PooledByteBuf<T> buf, int reqCapacity, int normCapacity) {
    // 如果沒有head或超過最大容量,那么返回false,表示分配失敗
    if (head == null || normCapacity > maxCapacity) {
        return false;
    }

    // 遍歷chunklist
    for (PoolChunk<T> cur = head;;) {
        // 去chunk中申請空間
        long handle = cur.allocate(normCapacity);
        // 如果handle<0, 說明申請失敗, 繼續(xù)滾動到下一個chunk循環(huán)
        if (handle < 0) {
            cur = cur.next;
            if (cur == null) {
                return false;
            }
        } else {
            // 如果申請成功, 那么將內(nèi)存空間與ByteBuf進行綁定
            cur.initBuf(buf, handle, reqCapacity);
            // 接著計算當前chunk的使用率,如果超過最大閾值,那么從當前l(fā)ist中刪除,并移動到下個list
            // 也就是升艙處理
            if (cur.usage() >= maxUsage) {
                remove(cur);
                nextList.add(cur);
            }
            return true;
        }
    }
}

釋放

boolean free(PoolChunk<T> chunk, long handle) {
    // 釋放該chunk對應的handle持有的內(nèi)存空間
    chunk.free(handle);
    // 如果小于最下,那么同理需要降級處理
    if (chunk.usage() < minUsage) {
        remove(chunk);
        // Move the PoolChunk down the PoolChunkList linked-list.
        return move0(chunk);
    }
    return true;
}

移動

private boolean move0(PoolChunk<T> chunk) {
    if (prevList == null) {
        assert chunk.usage() == 0;
        return false;
    }
    return prevList.move(chunk);
}
private boolean move(PoolChunk<T> chunk) {
    // 接著move0的上下文,這里已經(jīng)到了prevlist, 判斷是否滿足該list的使用率條件
    assert chunk.usage() < maxUsage;
    
    // 如果還是低于該區(qū)的最小,那么繼續(xù)降級
    if (chunk.usage() < minUsage) {
        return move0(chunk);
    }

    // 否則add到該list
    add0(chunk);
    return true;
}

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末速址,一起剝皮案震驚了整個濱河市奏窑,隨后出現(xiàn)的幾起案子金顿,更是在濱河造成了極大的恐慌醒颖,老刑警劉巖剿另,帶你破解...
    沈念sama閱讀 217,084評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件雇锡,死亡現(xiàn)場離奇詭異逛钻,居然都是意外死亡,警方通過查閱死者的電腦和手機锰提,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評論 3 392
  • 文/潘曉璐 我一進店門曙痘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人立肘,你說我怎么就攤上這事边坤〈V樱” “怎么了凌箕?”我有些...
    開封第一講書人閱讀 163,450評論 0 353
  • 文/不壞的土叔 我叫張陵椭更,是天一觀的道長玖雁。 經(jīng)常有香客問我,道長灶伊,這世上最難降的妖魔是什么援制? 我笑而不...
    開封第一講書人閱讀 58,322評論 1 293
  • 正文 為了忘掉前任赠摇,我火速辦了婚禮超燃,結(jié)果婚禮上区拳,老公的妹妹穿的比我還像新娘。我一直安慰自己淋纲,他們只是感情好劳闹,可當我...
    茶點故事閱讀 67,370評論 6 390
  • 文/花漫 我一把揭開白布院究。 她就那樣靜靜地躺著洽瞬,像睡著了一般。 火紅的嫁衣襯著肌膚如雪业汰。 梳的紋絲不亂的頭發(fā)上伙窃,一...
    開封第一講書人閱讀 51,274評論 1 300
  • 那天,我揣著相機與錄音样漆,去河邊找鬼为障。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的鳍怨。 我是一名探鬼主播呻右,決...
    沈念sama閱讀 40,126評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼鞋喇!你這毒婦竟也來了声滥?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,980評論 0 275
  • 序言:老撾萬榮一對情侶失蹤侦香,失蹤者是張志新(化名)和其女友劉穎落塑,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體罐韩,經(jīng)...
    沈念sama閱讀 45,414評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡憾赁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,599評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了散吵。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片龙考。...
    茶點故事閱讀 39,773評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖矾睦,靈堂內(nèi)的尸體忽然破棺而出洲愤,到底是詐尸還是另有隱情,我是刑警寧澤顷锰,帶...
    沈念sama閱讀 35,470評論 5 344
  • 正文 年R本政府宣布柬赐,位于F島的核電站,受9級特大地震影響官紫,放射性物質(zhì)發(fā)生泄漏肛宋。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,080評論 3 327
  • 文/蒙蒙 一束世、第九天 我趴在偏房一處隱蔽的房頂上張望酝陈。 院中可真熱鬧,春花似錦毁涉、人聲如沸沉帮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽穆壕。三九已至,卻和暖如春其屏,著一層夾襖步出監(jiān)牢的瞬間喇勋,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評論 1 269
  • 我被黑心中介騙來泰國打工偎行, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留川背,地道東北人贰拿。 一個月前我還...
    沈念sama閱讀 47,865評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像熄云,于是被迫代替她去往敵國和親膨更。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,689評論 2 354

推薦閱讀更多精彩內(nèi)容