Netty之ByteBuf深入分析

Netty之ByteBuf深入分析

[TOC]

分析思路

内存与内存管理器的抽象

ByteBuf 结构以及重要的API

ByteBuf 数据结构
* {@link ByteBuf} provides two pointer variables to support sequential
 * read and write operations - {@link #readerIndex() readerIndex} for a read
 * operation and {@link #writerIndex() writerIndex} for a write operation
 * respectively.  The following diagram shows how a buffer is segmented into
 * three areas by the two pointers:
 *
 * <pre>
 *      +-------------------+------------------+------------------+
 *      | discardable bytes |  readable bytes  |  writable bytes  |
 *      |                   |     (CONTENT)    |                  |
 *      +-------------------+------------------+------------------+
 *      |                   |                  |                  |
 *      0      <=      readerIndex   <=   writerIndex    <=    capacity
 * </pre>
 *
 * <h4>Readable bytes (the actual content)</h4>
read ,write set 方法
mark 和 reset方法

ByteBuf 分类

Pooled 和 Unpooled

Pooled池化内存分配每次从预先分配好的一块内存取一段连续内存封装成ByteBuf提供给应用程序,

Unpooled非池化每次进行内存分配的时候调用系统API向操作系统申请一块内存

Unsafe 和 非Unsafe

Unsafe直接获取ByteBuf在JVM内存地址调用JDK的Unsafe进行读写操作,通过ByteBuf分配内存首地址和当前指针基于内存偏移地址获取值,

非Unsafe不依赖JDK的Unsafe对象,通过内存数组和索引获取值

Heap和Direct

Heap在堆上进行内存分配,分配内存需要被GC管理,无需手动释放内存,依赖底层byte数组,

Direct调用JDK的API进行内存分配,分配内存不受JVM控制最终不会参与GC过程,需要手动释放内存避免造成内存无法释放,依赖DirectByteBuffer对象内存

内存分配器ByteBufAllocator分析

ByteBufAllocator功能

buffer()方法分配内存是否为Direct/Heap内存依赖具体实现,

ioBuffer()方法分配内存更希望是适合IO的Direct Buffer,directBuffer()/headBuffer()方法堆内/堆外进行内存分配,compositeBuffer()方法分配将两个ByteBuf合并变成CompositeByteBuf

AbstractByteBufAllocator

buffer()方法分配Buffer依赖实现分配内存,调用directBuffer()/heapBuffer()方法分配默认Buffer容量和最大扩充容量的ByteBuf,newDirectBuffer()/newHeapBuffer()方法分配Pooled/Unpooled依赖底层实现

ByteBufAllocator两个子类

PooledByteBufAllocator从预先分配好的内存取一段内存,

UnpooledByteBufAllocator调用系统API分配内存,调用hasUnsafe()方法获取Unsafe决定分配Unsafe/非Unsafe

UnpooledByteBufAllocator分析
heap内存的分配

newHeapBuffer()方法通过hasUnsafe()方法判断是否有Unsafe

传递initialCapacity容量Byte数组参数setArray()方法设置array以及setIndex()方法设置读/写指针

创建UnpooledUnsafeHeapByteBuf/UnpooledHeapByteBuf,

_get***()方法通过Unsafe方式返回数组对象偏移量[BYTE_ARRAY_BASE_OFFSET+index]对应的byte/数组索引方式返回array数组index位置byte

direct内存的分配

newDirectBuffer()方法通过hasUnsafe()方法判断是否有Unsafe

调用allocateDirect(initialCapacity)创建DirectByteBuffer

使用setByteBuffer()方法设置buffer[UnpooledUnsafeDirectByteBuf

使用directBufferAddress()方法获取buffer内存地址设置memoryAddress


创建UnpooledUnsafeDirectByteBuf/UnpooledDirectByteBuf,

_get***()方法通过addr()方法memoryAdress+index计算内存地址

Unsafe获取对应这块内存的byte/ByteBuffer获取buffer index位置对应的byte

不同规格大小和不同类别的内存的分配策略

内存规格介绍

 0 <-tiny->512B<-small->8K<-normal->16M<-huge->
 |______________________|            |
          SubPage      Page        Chunk

16M作为分界点对应的Chunk,

所有的内存申请以Chunk为单位向操作系统申请,

内存分配在Chunk里面执行相应操作,

16M Chunk按照Page进行切分为2048个Page,8K Page按照SubPage切分

内存的回收过程


常见问题

Netty 的内存的类别有哪些?

堆内内存/堆外内存

堆内[基于2048byte字节内存数组分配]

堆外[基于JDK的DirectByteBuffer内存分配]

Unsafe/非Unsafe

Unsafe[通过JDK的Unsafe对象基于物理内存地址进行数据读写]

非Unsafe[调用JDK的API进行读写]

UnPooled/Pooled

UnPooled[每次分配内存申请内存]

Pooled[预先分配好一整块内存,分配的时候用一定算法从一整块内存取出一块连续内存]

如何减少多线程内存分配之间的竞争关系?

PooledByteBufAllocator内存分配器结构维护Arena数组,所有的内存分配都在Arena上进行,

通过PoolThreadCache对象将线程和Arena进行一一绑定, 默认情况一个Nio线程管理一个Arena实现多线程内存分配相互不受影响减少多线程内存分配之间的竞争

不同大小的内存是如何进行分配的?

Page级别的内存分配通过完全二叉树的标记查找某一段连续内存,

Page级别以下的内存分配首先查找到Page然后把此Page按照SubPage大小进行划分最后通过位图的方式进行内存分配

不同大小的内存是如何进行分配的?2

Netty一次向系统申请16M的连续内存空间,这块内存通过PoolChunk对象包装,进一步的把这16M内存分成了2048个页(pageSize=8k)。页作为Netty内存管理的最基本的单位 ,所有的内存分配首先必须申请一块空闲页。
对于小内存(小于4096)的分配还会将Page细化成更小的单位Subpage。Subpage按大小分有两大类,36种情况:Tiny:小于512的情况,最小空间为16,对齐大小为16,区间为[16,512),所以共有32种情况。Small:大于等于512的情况,总共有四种,512,1024,2048,4096。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,607评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,047评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,496评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,405评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,400评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,479评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,883评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,535评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,743评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,544评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,612评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,309评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,881评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,891评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,136评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,783评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,316评论 2 342

推荐阅读更多精彩内容

  • 文丨卓海平 图丨源自网络 前几天一位赛车手的自谋体人在群里发牢骚,说他刚碰到一群很极端的素食主义,那些人将个人饮食...
    卖水果的老卓阅读 436评论 0 0
  • 每个人的性格本就不同 我强求不了你 也无法做到迎合 世人说相处需磨合 磨合期却是最考究人耐心的时段 每个人都是背负...
    爆哥_阅读 228评论 0 0
  • session4思考题:你的企业/产品如何进行差异化定位? 产品所在地为烟台市的某一个原生态岛屿,差异化的核心主打...
    豆豆的麻麻_阅读 383评论 1 1