netty内存分配总览

netty的内存分配总体上思路是参考jemalloc
jemalloc介绍:
http://jemalloc.net/
https://people.freebsd.org/~jasone/jemalloc/bsdcan2006/jemalloc.pdf
中文版:
https://blog.csdn.net/stillingpb/article/details/50937366
如果对jemalloc源码感兴趣、可以参考如下系列文章
https://www.jianshu.com/p/f1988cc08dfd

这里贴出一张jemalloc内存划分视图


netty内存分配总览_第1张图片
image.png

如上图所示jemalloc对内存的划分遵循由大到小、逐层分配:

  1. 内存是由一定数量的arean进行管理的.
    对应于netty中就是PoolArena,netty在实例化内存分配器ByteBufAlloctor的时候初始化PoolArean的数量为 2倍的cpu核数
    netty为什么将内存根据arean划分为不同的块?
    参考 https://blog.csdn.net/stillingpb/article/details/50937366
  2. 一个arena被分割成若干chunks,作为向操作系统请求的内存的基本单元。
    在netty中多个chunk之间根据不同的使用率分类并且之间通过双向链表进行关联。
  3. chunk内部又包含着若干runs, 作为分配小块内存的基本单元.
    在netty中chunk的默认大小为16M、通过一个完全二叉树进行管理、这个完全二叉树的叶子节点的大小就是一个page的大小、默认为8k,多个page组成一个run、当请求内存大小大于page、netty中分配一个run的大小、也就是多个page块。
  4. run由pages组成, 最终被划分成一定数量的regions.
    在netty中如请求的内存大于一个page(8k),那么poolChunk会分配多个page给应用程序也就是一个Run,同时一个page也可继续被分割为若干个子regions、作为netty内存分配的最小单元,在netty中也即是一个PoolSubpage。

netty内存分配流程

首先举一个生活中例子。假如我下了一个单,订购一块 N 字节的内存,并等待它的到达。怎样做到即时送达?

  • 如果订购的内存是个小件(好比一块橡皮、一本书或是一个微波炉等),那么直接从同城仓库送出。
  • 如果订购的内存是个大件(好比电视机、空调等),那么得从区域仓库(例如华东区仓库)送出。
  • 如果订购的内存是个巨大件(好比汽车、轮船),那么得从全国仓库送出。
  • 在 netty 类比以上的物流系统中
    同城仓库相当于 PoolThreadCache —— 线程独有的内存仓库;
    区域仓库相当于 PoolArean —— 几个线程共享的内存仓库;
    全国仓库相当于全局变量指向的内存仓库,为所有线程可用。
    在 netty 中,整块批发内存,之后或拆开零售,或整块出售。整块批发的内存叫做 chunk,对于小件和大件订单,则进一步拆成 run。
    Chunk 的大小为 16MB(可调)或其倍数,如果是堆外内存、那么根据16M对齐;而 run 大小为页大小(8k)的整数倍。
    netty中整个内存分配可以用以下图来展示:


    netty内存分配总览_第2张图片
    image.png

你可能感兴趣的:(netty内存分配总览)