netty的內(nèi)存分配總體上思路是參考jemalloc
jemalloc介紹:
http://jemalloc.net/
https://people.freebsd.org/~jasone/jemalloc/bsdcan2006/jemalloc.pdf
中文版:
https://blog.csdn.net/stillingpb/article/details/50937366
如果對jemalloc源碼感興趣娘汞、可以參考如下系列文章
http://www.reibang.com/p/f1988cc08dfd
這里貼出一張jemalloc內(nèi)存劃分視圖
如上圖所示jemalloc對內(nèi)存的劃分遵循由大到小挡育、逐層分配:
- 內(nèi)存是由一定數(shù)量的arean進行管理的.
對應(yīng)于netty中就是PoolArena咙俩,netty在實例化內(nèi)存分配器ByteBufAlloctor的時候初始化PoolArean的數(shù)量為 2倍的cpu核數(shù)
netty為什么將內(nèi)存根據(jù)arean劃分為不同的塊?
參考 https://blog.csdn.net/stillingpb/article/details/50937366 - 一個arena被分割成若干chunks,作為向操作系統(tǒng)請求的內(nèi)存的基本單元妖谴。
在netty中多個chunk之間根據(jù)不同的使用率分類并且之間通過雙向鏈表進行關(guān)聯(lián)簿煌。 - chunk內(nèi)部又包含著若干runs, 作為分配小塊內(nèi)存的基本單元.
在netty中chunk的默認(rèn)大小為16M、通過一個完全二叉樹進行管理褒侧、這個完全二叉樹的葉子節(jié)點的大小就是一個page的大小良风、默認(rèn)為8k,多個page組成一個run闷供、當(dāng)請求內(nèi)存大小大于page烟央、netty中分配一個run的大小、也就是多個page塊歪脏。 - run由pages組成, 最終被劃分成一定數(shù)量的regions.
在netty中如請求的內(nèi)存大于一個page(8k)疑俭,那么poolChunk會分配多個page給應(yīng)用程序也就是一個Run,同時一個page也可繼續(xù)被分割為若干個子regions、作為netty內(nèi)存分配的最小單元婿失,在netty中也即是一個PoolSubpage钞艇。
netty內(nèi)存分配流程
首先舉一個生活中例子。假如我下了一個單豪硅,訂購一塊 N 字節(jié)的內(nèi)存香璃,并等待它的到達(dá)。怎樣做到即時送達(dá)舟误?
- 如果訂購的內(nèi)存是個小件(好比一塊橡皮葡秒、一本書或是一個微波爐等),那么直接從同城倉庫送出嵌溢。
- 如果訂購的內(nèi)存是個大件(好比電視機眯牧、空調(diào)等),那么得從區(qū)域倉庫(例如華東區(qū)倉庫)送出赖草。
- 如果訂購的內(nèi)存是個巨大件(好比汽車学少、輪船),那么得從全國倉庫送出秧骑。
-
在 netty 類比以上的物流系統(tǒng)中
同城倉庫相當(dāng)于 PoolThreadCache —— 線程獨有的內(nèi)存?zhèn)}庫版确;
區(qū)域倉庫相當(dāng)于 PoolArean —— 幾個線程共享的內(nèi)存?zhèn)}庫;
全國倉庫相當(dāng)于全局變量指向的內(nèi)存?zhèn)}庫乎折,為所有線程可用绒疗。
在 netty 中,整塊批發(fā)內(nèi)存骂澄,之后或拆開零售吓蘑,或整塊出售。整塊批發(fā)的內(nèi)存叫做 chunk,對于小件和大件訂單磨镶,則進一步拆成 run溃蔫。
Chunk 的大小為 16MB(可調(diào))或其倍數(shù),如果是堆外內(nèi)存琳猫、那么根據(jù)16M對齊伟叛;而 run 大小為頁大小(8k)的整數(shù)倍。
netty中整個內(nèi)存分配可以用以下圖來展示: