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://m.itdecent.cn/p/f1988cc08dfd
這里貼出一張jemalloc內(nèi)存劃分視圖

如上圖所示jemalloc對內(nèi)存的劃分遵循由大到小、逐層分配:
- 內(nèi)存是由一定數(shù)量的arean進(jìn)行管理的.
對應(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ù)不同的使用率分類并且之間通過雙向鏈表進(jìn)行關(guān)聯(lián)。 - chunk內(nèi)部又包含著若干runs, 作為分配小塊內(nèi)存的基本單元.
在netty中chunk的默認(rèn)大小為16M、通過一個完全二叉樹進(jìn)行管理、這個完全二叉樹的葉子節(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)存是個大件(好比電視機(jī)、空調(diào)等),那么得從區(qū)域倉庫(例如華東區(qū)倉庫)送出。
- 如果訂購的內(nèi)存是個巨大件(好比汽車、輪船),那么得從全國倉庫送出。
-
在 netty 類比以上的物流系統(tǒng)中
同城倉庫相當(dāng)于 PoolThreadCache —— 線程獨(dú)有的內(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,對于小件和大件訂單,則進(jìn)一步拆成 run。
Chunk 的大小為 16MB(可調(diào))或其倍數(shù),如果是堆外內(nèi)存、那么根據(jù)16M對齊;而 run 大小為頁大小(8k)的整數(shù)倍。
netty中整個內(nèi)存分配可以用以下圖來展示:
image.png
