Netty之ByteBuf深入分析

Netty之ByteBuf深入分析

[TOC]

分析思路

內(nèi)存與內(nèi)存管理器的抽象

ByteBuf 結(jié)構(gòu)以及重要的API

ByteBuf 數(shù)據(jù)結(jié)構(gòu)
* {@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池化內(nèi)存分配每次從預(yù)先分配好的一塊內(nèi)存取一段連續(xù)內(nèi)存封裝成ByteBuf提供給應(yīng)用程序,

Unpooled非池化每次進行內(nèi)存分配的時候調(diào)用系統(tǒng)API向操作系統(tǒng)申請一塊內(nèi)存

Unsafe 和 非Unsafe

Unsafe直接獲取ByteBuf在JVM內(nèi)存地址調(diào)用JDK的Unsafe進行讀寫操作,通過ByteBuf分配內(nèi)存首地址和當(dāng)前指針基于內(nèi)存偏移地址獲取值,

非Unsafe不依賴JDK的Unsafe對象,通過內(nèi)存數(shù)組和索引獲取值

Heap和Direct

Heap在堆上進行內(nèi)存分配,分配內(nèi)存需要被GC管理,無需手動釋放內(nèi)存,依賴底層byte數(shù)組,

Direct調(diào)用JDK的API進行內(nèi)存分配,分配內(nèi)存不受JVM控制最終不會參與GC過程,需要手動釋放內(nèi)存避免造成內(nèi)存無法釋放,依賴DirectByteBuffer對象內(nèi)存

內(nèi)存分配器ByteBufAllocator分析

ByteBufAllocator功能

buffer()方法分配內(nèi)存是否為Direct/Heap內(nèi)存依賴具體實現(xiàn),

ioBuffer()方法分配內(nèi)存更希望是適合IO的Direct Buffer,directBuffer()/headBuffer()方法堆內(nèi)/堆外進行內(nèi)存分配,compositeBuffer()方法分配將兩個ByteBuf合并變成CompositeByteBuf

AbstractByteBufAllocator

buffer()方法分配Buffer依賴實現(xiàn)分配內(nèi)存,調(diào)用directBuffer()/heapBuffer()方法分配默認(rèn)Buffer容量和最大擴充容量的ByteBuf,newDirectBuffer()/newHeapBuffer()方法分配Pooled/Unpooled依賴底層實現(xiàn)

ByteBufAllocator兩個子類

PooledByteBufAllocator從預(yù)先分配好的內(nèi)存取一段內(nèi)存,

UnpooledByteBufAllocator調(diào)用系統(tǒng)API分配內(nèi)存,調(diào)用hasUnsafe()方法獲取Unsafe決定分配Unsafe/非Unsafe

UnpooledByteBufAllocator分析
heap內(nèi)存的分配

newHeapBuffer()方法通過hasUnsafe()方法判斷是否有Unsafe

傳遞initialCapacity容量Byte數(shù)組參數(shù)setArray()方法設(shè)置array以及setIndex()方法設(shè)置讀/寫指針

創(chuàng)建UnpooledUnsafeHeapByteBuf/UnpooledHeapByteBuf,

_get***()方法通過Unsafe方式返回數(shù)組對象偏移量[BYTE_ARRAY_BASE_OFFSET+index]對應(yīng)的byte/數(shù)組索引方式返回array數(shù)組index位置byte

direct內(nèi)存的分配

newDirectBuffer()方法通過hasUnsafe()方法判斷是否有Unsafe

調(diào)用allocateDirect(initialCapacity)創(chuàng)建DirectByteBuffer

使用setByteBuffer()方法設(shè)置buffer[UnpooledUnsafeDirectByteBuf

使用directBufferAddress()方法獲取buffer內(nèi)存地址設(shè)置memoryAddress


創(chuàng)建UnpooledUnsafeDirectByteBuf/UnpooledDirectByteBuf,

_get***()方法通過addr()方法memoryAdress+index計算內(nèi)存地址

Unsafe獲取對應(yīng)這塊內(nèi)存的byte/ByteBuffer獲取buffer index位置對應(yīng)的byte

不同規(guī)格大小和不同類別的內(nèi)存的分配策略

內(nèi)存規(guī)格介紹

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

16M作為分界點對應(yīng)的Chunk,

所有的內(nèi)存申請以Chunk為單位向操作系統(tǒng)申請,

內(nèi)存分配在Chunk里面執(zhí)行相應(yīng)操作,

16M Chunk按照Page進行切分為2048個Page,8K Page按照SubPage切分

內(nèi)存的回收過程


常見問題

Netty 的內(nèi)存的類別有哪些?

堆內(nèi)內(nèi)存/堆外內(nèi)存

堆內(nèi)[基于2048byte字節(jié)內(nèi)存數(shù)組分配]

堆外[基于JDK的DirectByteBuffer內(nèi)存分配]

Unsafe/非Unsafe

Unsafe[通過JDK的Unsafe對象基于物理內(nèi)存地址進行數(shù)據(jù)讀寫]

非Unsafe[調(diào)用JDK的API進行讀寫]

UnPooled/Pooled

UnPooled[每次分配內(nèi)存申請內(nèi)存]

Pooled[預(yù)先分配好一整塊內(nèi)存,分配的時候用一定算法從一整塊內(nèi)存取出一塊連續(xù)內(nèi)存]

如何減少多線程內(nèi)存分配之間的競爭關(guān)系?

PooledByteBufAllocator內(nèi)存分配器結(jié)構(gòu)維護Arena數(shù)組,所有的內(nèi)存分配都在Arena上進行,

通過PoolThreadCache對象將線程和Arena進行一一綁定, 默認(rèn)情況一個Nio線程管理一個Arena實現(xiàn)多線程內(nèi)存分配相互不受影響減少多線程內(nèi)存分配之間的競爭

不同大小的內(nèi)存是如何進行分配的?

Page級別的內(nèi)存分配通過完全二叉樹的標(biāo)記查找某一段連續(xù)內(nèi)存,

Page級別以下的內(nèi)存分配首先查找到Page然后把此Page按照SubPage大小進行劃分最后通過位圖的方式進行內(nèi)存分配

不同大小的內(nèi)存是如何進行分配的愧捕?2

Netty一次向系統(tǒng)申請16M的連續(xù)內(nèi)存空間酬凳,這塊內(nèi)存通過PoolChunk對象包裝服猪,進一步的把這16M內(nèi)存分成了2048個頁(pageSize=8k)正林。頁作為Netty內(nèi)存管理的最基本的單位 首装,所有的內(nèi)存分配首先必須申請一塊空閑頁脓魏。
對于小內(nèi)存(小于4096)的分配還會將Page細(xì)化成更小的單位Subpage兰吟。Subpage按大小分有兩大類,36種情況:Tiny:小于512的情況茂翔,最小空間為16混蔼,對齊大小為16,區(qū)間為[16,512)珊燎,所以共有32種情況惭嚣。Small:大于等于512的情況,總共有四種悔政,512,1024,2048,4096晚吞。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市谋国,隨后出現(xiàn)的幾起案子槽地,更是在濱河造成了極大的恐慌,老刑警劉巖芦瘾,帶你破解...
    沈念sama閱讀 217,826評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件闷盔,死亡現(xiàn)場離奇詭異,居然都是意外死亡旅急,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評論 3 395
  • 文/潘曉璐 我一進店門牡整,熙熙樓的掌柜王于貴愁眉苦臉地迎上來藐吮,“玉大人,你說我怎么就攤上這事∫ゴ牵” “怎么了迫摔?”我有些...
    開封第一講書人閱讀 164,234評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長泥从。 經(jīng)常有香客問我句占,道長,這世上最難降的妖魔是什么躯嫉? 我笑而不...
    開封第一講書人閱讀 58,562評論 1 293
  • 正文 為了忘掉前任纱烘,我火速辦了婚禮,結(jié)果婚禮上祈餐,老公的妹妹穿的比我還像新娘擂啥。我一直安慰自己,他們只是感情好帆阳,可當(dāng)我...
    茶點故事閱讀 67,611評論 6 392
  • 文/花漫 我一把揭開白布哺壶。 她就那樣靜靜地躺著,像睡著了一般蜒谤。 火紅的嫁衣襯著肌膚如雪山宾。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,482評論 1 302
  • 那天鳍徽,我揣著相機與錄音资锰,去河邊找鬼。 笑死旬盯,一個胖子當(dāng)著我的面吹牛台妆,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播胖翰,決...
    沈念sama閱讀 40,271評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼接剩,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了萨咳?” 一聲冷哼從身側(cè)響起懊缺,我...
    開封第一講書人閱讀 39,166評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎培他,沒想到半個月后鹃两,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,608評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡舀凛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,814評論 3 336
  • 正文 我和宋清朗相戀三年俊扳,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片猛遍。...
    茶點故事閱讀 39,926評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡馋记,死狀恐怖号坡,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情梯醒,我是刑警寧澤宽堆,帶...
    沈念sama閱讀 35,644評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站茸习,受9級特大地震影響畜隶,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜号胚,卻給世界環(huán)境...
    茶點故事閱讀 41,249評論 3 329
  • 文/蒙蒙 一籽慢、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧涕刚,春花似錦嗡综、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至驾茴,卻和暖如春盼樟,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背锈至。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評論 1 269
  • 我被黑心中介騙來泰國打工晨缴, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人峡捡。 一個月前我還...
    沈念sama閱讀 48,063評論 3 370
  • 正文 我出身青樓击碗,卻偏偏與公主長得像,于是被迫代替她去往敵國和親们拙。 傳聞我的和親對象是個殘疾皇子稍途,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,871評論 2 354

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

  • 文丨卓海平 圖丨源自網(wǎng)絡(luò) 前幾天一位賽車手的自謀體人在群里發(fā)牢騷械拍,說他剛碰到一群很極端的素食主義,那些人將個人飲食...
    賣水果的老卓閱讀 452評論 0 0
  • 每個人的性格本就不同 我強求不了你 也無法做到迎合 世人說相處需磨合 磨合期卻是最考究人耐心的時段 每個人都是背負(fù)...
    爆哥_閱讀 232評論 0 0
  • session4思考題:你的企業(yè)/產(chǎn)品如何進行差異化定位? 產(chǎn)品所在地為煙臺市的某一個原生態(tài)島嶼埂奈,差異化的核心主打...
    豆豆的麻麻_閱讀 389評論 1 1