Netty內(nèi)存模型-PoolArena

1 原理

應(yīng)用層的內(nèi)存分配最終是委托給PoolArena實現(xiàn)瞧预。先看下PoolArena的內(nèi)部數(shù)據(jù)結(jié)構(gòu):

image

poolArena提供了兩種方式進行內(nèi)存分配:

  • PoolSubpage用于分配小于8k的內(nèi)存沿腰;

tinySubpagePools:用于分配小于512字節(jié)的內(nèi)存,默認長度為32伐坏,因為內(nèi)存分配最小為16逝慧,每次增加16截驮,直到512婆瓜,區(qū)間[16快集,512)一共有32個不同值;

smallSubpagePools:用于分配大于等于512字節(jié)的內(nèi)存廉白,默認長度為4个初;

tinySubpagePools和smallSubpagePools中的元素都是默認subpage。

  • poolChunkList用于分配大于8k的內(nèi)存猴蹂;

qInit:存儲內(nèi)存利用率0-25%的chunk

q000:存儲內(nèi)存利用率1-50%的chunk

q025:存儲內(nèi)存利用率25-75%的chunk

q050:存儲內(nèi)存利用率50-100%的chunk

q075:存儲內(nèi)存利用率75-100%的chunk

q100:存儲內(nèi)存利用率100%的chunk

各chunkList連接如下:

image

按照內(nèi)存的使用率來取名的院溺,如qInit代表一個chunk最開始分配后會進入它,隨著其使用率增大會逐漸從q000到q100磅轻,而隨著內(nèi)存釋放覆获,使用率減小,它又會慢慢的從q100到q00,最終這個chunk上的所有內(nèi)存釋放后瓢省,整個chunk被回收。

接下來看下PoolArena如何進行內(nèi)存分配痊班,如下勤婚。

image
  • 如果是分配小內(nèi)存,則嘗試從tinySubpagePools或smallSubpagePools中分配內(nèi)存涤伐,如果沒有合適subpage馒胆,則采用方法allocateNormal分配內(nèi)存缨称。

  • 如果分配一個page以上的內(nèi)存,直接采用方法allocateNormal分配內(nèi)存祝迂。

默認都是先嘗試從poolThreadCache中分配內(nèi)存睦尽,PoolThreadCache利用ThreadLocal的特性,消除了多線程競爭型雳,提高內(nèi)存分配效率当凡;首次分配時,poolThreadCache中并沒有可用內(nèi)存進行分配纠俭,當上一次分配的內(nèi)存使用完并釋放時沿量,會將其加入到poolThreadCache中,提供該線程下次申請時使用冤荆。

內(nèi)存池內(nèi)存分配流程:

1朴则、ByteBufAllocator 準備申請一塊內(nèi)存;

2钓简、嘗試從PoolThreadCache中獲取可用內(nèi)存乌妒,如果成功則完成此次分配,否則繼續(xù)往下走外邓,注意后面的內(nèi)存分配都會加鎖撤蚊;

3、如果是小塊(可配置該值)內(nèi)存分配坐榆,則嘗試從PoolArena中緩存的PoolSubpage中獲取內(nèi)存拴魄,如果成功則完成此次分配;

4席镀、如果是普通大小的內(nèi)存分配匹中,則從PoolChunkList中查找可用PoolChunk并進行內(nèi)存分配,如果沒有可用的PoolChunk則創(chuàng)建一個并加入到PoolChunkList中豪诲,完成此次內(nèi)存分配顶捷;

5、如果是大塊(大于一個chunk的大惺豪椤)內(nèi)存分配服赎,則直接分配內(nèi)存而不用內(nèi)存池的方式;

6交播、內(nèi)存使用完成后進行釋放重虑,釋放的時候首先判斷是否和分配的時候是同一個線程,如果是則嘗試將其放入PoolThreadCache秦士,這塊內(nèi)存將會在下一次同一個線程申請內(nèi)存時使用缺厉,即前面的步驟2;

7、如果不是同一個線程提针,則回收至chunk中命爬,此時chunk中的內(nèi)存使用率會發(fā)生變化,可能導(dǎo)致該chunk在不同的PoolChunkList中移動辐脖,或者整個chunk回收(chunk在q000上饲宛,且其分配的所有內(nèi)存被釋放);同時如果釋放的是小塊內(nèi)存(與步驟3中描述的內(nèi)存相同)嗜价,會嘗試將小塊內(nèi)存前置到PoolArena中艇抠,這里操作成功了,步驟3的操作中才可能成功炭剪。

allocateNormal實現(xiàn)如下:

image

第一次進行內(nèi)存分配時练链,chunkList沒有chunk可以分配內(nèi)存,需通過方法newChunk新建一個chunk進行內(nèi)存分配奴拦,并添加到qInit列表中媒鼓。如果分配如512字節(jié)的小內(nèi)存,除了創(chuàng)建chunk错妖,還有創(chuàng)建subpage绿鸣,PoolSubpage在初始化之后,會添加到smallSubpagePools中暂氯,其實并不是直接插入到數(shù)組潮模,而是添加到head的next節(jié)點。下次再有分配512字節(jié)的需求時痴施,直接從smallSubpagePools獲取對應(yīng)的subpage進行分配擎厢。

  • 這里為什么不是從較低的q000開始呢,我們知道一個chunk隨著內(nèi)存的不停釋放辣吃,它本身會不停的往其所在的chunk list的prev list移動动遭,直到其完全釋放后被回收。 如果這里是從q000開始嘗試分配神得,雖然分配的速度可能更快了(因為分配成功的幾率更大)厘惦,但一個chunk在使用率為25%以內(nèi)時有更大幾率再分配,也就是一個chunk被回收的幾率大大降低了哩簿。這樣就帶來了一個問題宵蕉,我們的應(yīng)用在實際運行過程中會存在一個訪問高峰期,這個時候內(nèi)存的占用量會是平時的幾倍节榜,因此會多分配幾倍的chunk出來羡玛,而等高峰期過去以后,由于chunk被回收的幾率降低宗苍,內(nèi)存回收的進度就會很慢(因為沒被完全釋放稼稿,所以無法回收)亿遂,內(nèi)存就存在很大的浪費。

  • 為什么是從q050開始嘗試分配呢渺杉,q050是內(nèi)存占用50%~100%的chunk,能夠提高整個應(yīng)用的內(nèi)存使用率挪钓,因為這樣大部分情況下會使用q050的內(nèi)存是越,這樣在內(nèi)存使用不是很多的情況下一些利用率低(<50%)的chunk慢慢就會淘汰出去,最終被回收碌上。

  • 為什么不是從qinit中開始呢倚评,這里的chunk利用率低,但又不會被回收馏予,會形成浪費

  • q075,q100由于使用率高天梧,分配成功的幾率也會更小,因此放到最后霞丧。如果整個list中都無法分配呢岗,則新建一個chunk,并將其加入到qinit中蛹尝。

Refereneces

  1. http://www.reibang.com/p/4856bd30dd56

  2. https://blog.csdn.net/youaremoon/article/details/50042373

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末后豫,一起剝皮案震驚了整個濱河市藕筋,隨后出現(xiàn)的幾起案子概疆,更是在濱河造成了極大的恐慌,老刑警劉巖芯义,帶你破解...
    沈念sama閱讀 216,651評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件愕难,死亡現(xiàn)場離奇詭異早龟,居然都是意外死亡,警方通過查閱死者的電腦和手機猫缭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評論 3 392
  • 文/潘曉璐 我一進店門葱弟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人饵骨,你說我怎么就攤上這事翘悉。” “怎么了居触?”我有些...
    開封第一講書人閱讀 162,931評論 0 353
  • 文/不壞的土叔 我叫張陵妖混,是天一觀的道長。 經(jīng)常有香客問我轮洋,道長制市,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,218評論 1 292
  • 正文 為了忘掉前任弊予,我火速辦了婚禮祥楣,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己误褪,他們只是感情好责鳍,可當我...
    茶點故事閱讀 67,234評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著兽间,像睡著了一般历葛。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上嘀略,一...
    開封第一講書人閱讀 51,198評論 1 299
  • 那天恤溶,我揣著相機與錄音,去河邊找鬼帜羊。 笑死咒程,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的讼育。 我是一名探鬼主播帐姻,決...
    沈念sama閱讀 40,084評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼窥淆!你這毒婦竟也來了卖宠?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,926評論 0 274
  • 序言:老撾萬榮一對情侶失蹤忧饭,失蹤者是張志新(化名)和其女友劉穎扛伍,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體词裤,經(jīng)...
    沈念sama閱讀 45,341評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡刺洒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,563評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了吼砂。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片逆航。...
    茶點故事閱讀 39,731評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖渔肩,靈堂內(nèi)的尸體忽然破棺而出因俐,到底是詐尸還是另有隱情,我是刑警寧澤周偎,帶...
    沈念sama閱讀 35,430評論 5 343
  • 正文 年R本政府宣布抹剩,位于F島的核電站,受9級特大地震影響蓉坎,放射性物質(zhì)發(fā)生泄漏澳眷。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,036評論 3 326
  • 文/蒙蒙 一蛉艾、第九天 我趴在偏房一處隱蔽的房頂上張望钳踊。 院中可真熱鬧衷敌,春花似錦、人聲如沸拓瞪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽祭埂。三九已至瞒爬,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間沟堡,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評論 1 269
  • 我被黑心中介騙來泰國打工矢空, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留航罗,地道東北人。 一個月前我還...
    沈念sama閱讀 47,743評論 2 368
  • 正文 我出身青樓屁药,卻偏偏與公主長得像粥血,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子酿箭,可洞房花燭夜當晚...
    茶點故事閱讀 44,629評論 2 354

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