摘要:對于小內(nèi)存小于的分配還會將細化成更小的單位。按大小分有兩大類,種情況小于的情況,最小空間為,對齊大小為,區(qū)間為,所以共有種情況。大于等于的情況,總共有四種,。
Netty之ByteBuf深入分析
[TOC]
分析思路 內(nèi)存與內(nèi)存管理器的抽象 ByteBuf 結(jié)構(gòu)以及重要的API* {@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: * ** +-------------------+------------------+------------------+ * | discardable bytes | readable bytes | writable bytes | * | | (CONTENT) | | * +-------------------+------------------+------------------+ * | | | | * 0 <= readerIndex <= writerIndex <= capacity ** *Readable bytes (the actual content)
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直接獲取ByteBuf在JVM內(nèi)存地址調(diào)用JDK的Unsafe進行讀寫操作,通過ByteBuf分配內(nèi)存首地址和當(dāng)前指針基于內(nèi)存偏移地址獲取值,
非Unsafe不依賴JDK的Unsafe對象,通過內(nèi)存數(shù)組和索引獲取值
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分析buffer()方法分配內(nèi)存是否為Direct/Heap內(nèi)存依賴具體實現(xiàn),
ioBuffer()方法分配內(nèi)存更希望是適合IO的Direct Buffer,directBuffer()/headBuffer()方法堆內(nèi)/堆外進行內(nèi)存分配,compositeBuffer()方法分配將兩個ByteBuf合并變成CompositeByteBuf
buffer()方法分配Buffer依賴實現(xiàn)分配內(nèi)存,調(diào)用directBuffer()/heapBuffer()方法分配默認(rèn)Buffer容量和最大擴充容量的ByteBuf,newDirectBuffer()/newHeapBuffer()方法分配Pooled/Unpooled依賴底層實現(xiàn)
PooledByteBufAllocator從預(yù)先分配好的內(nèi)存取一段內(nèi)存,
UnpooledByteBufAllocator調(diào)用系統(tǒng)API分配內(nèi)存,調(diào)用hasUnsafe()方法獲取Unsafe決定分配Unsafe/非Unsafe
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
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/非UnsafeUnsafe[通過JDK的Unsafe對象基于物理內(nèi)存地址進行數(shù)據(jù)讀寫]
非Unsafe[調(diào)用JDK的API進行讀寫]
UnPooled/PooledUnPooled[每次分配內(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)存是如何進行分配的?2Netty一次向系統(tǒng)申請16M的連續(xù)內(nèi)存空間,這塊內(nèi)存通過PoolChunk對象包裝,進一步的把這16M內(nèi)存分成了2048個頁(pageSize=8k)。頁作為Netty內(nèi)存管理的最基本的單位 ,所有的內(nèi)存分配首先必須申請一塊空閑頁。
對于小內(nèi)存(小于4096)的分配還會將Page細化成更小的單位Subpage。Subpage按大小分有兩大類,36種情況:Tiny:小于512的情況,最小空間為16,對齊大小為16,區(qū)間為[16,512),所以共有32種情況。Small:大于等于512的情況,總共有四種,512,1024,2048,4096。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/77039.html
摘要:接上篇源碼分析之三我就是大名鼎鼎的一的處理循環(huán)在中一個需要負(fù)責(zé)兩個工作第一個是作為線程負(fù)責(zé)相應(yīng)的操作第二個是作為任務(wù)線程執(zhí)行中的任務(wù)接下來我們先從操縱方面入手看一下數(shù)據(jù)是如何從傳遞到我們的中的是模型的一個實現(xiàn)并且是基于的那么從的前生今世之四 接上篇Netty 源碼分析之 三 我就是大名鼎鼎的 EventLoop(一) Netty 的 IO 處理循環(huán) 在 Netty 中, 一個 Even...
摘要:維基百科中對的解釋是零拷貝技術(shù)是指計算機執(zhí)行操作時,不需要先將數(shù)據(jù)從某處內(nèi)存復(fù)制到另一個特定區(qū)域。維基百科里提到的零拷貝是在硬件和操作系統(tǒng)層面的,而本文主要介紹的是在應(yīng)用層面的優(yōu)化。 維基百科中對 Zero-copy 的解釋是 零拷貝技術(shù)是指計算機執(zhí)行操作時,CPU不需要先將數(shù)據(jù)從某處內(nèi)存復(fù)制到另一個特定區(qū)域。這種技術(shù)通常用于通過網(wǎng)絡(luò)傳輸文件時節(jié)省CPU周期和內(nèi)存帶寬。 維基百科里提到...
摘要:如果什么事都沒得做,它也不會死循環(huán),它會將線程休眠起來,直到下一個事件來了再繼續(xù)干活,這樣的一個線程稱之為線程。而請求處理邏輯既可以使用單獨的線程池進行處理,也可以跟放在讀寫線程一塊處理。 Netty到底是什么 從HTTP說起 有了Netty,你可以實現(xiàn)自己的HTTP服務(wù)器,F(xiàn)TP服務(wù)器,UDP服務(wù)器,RPC服務(wù)器,WebSocket服務(wù)器,Redis的Proxy服務(wù)器,MySQL的P...
摘要:主要用來檢測對象是否泄漏。子類實現(xiàn)相關(guān)的方法是否支持?jǐn)?shù)組,判斷緩沖區(qū)的實現(xiàn)是否基于字節(jié)數(shù)組如果緩沖區(qū)的實現(xiàn)基于字節(jié)數(shù)組,返回字節(jié)數(shù)組 ByteBuf ByteBuf需要提供JDK ByteBuffer的功能(包含且不限于),主要有以下幾類基本功能: 7種Java基礎(chǔ)類型、byte[]、ByteBuffer(ByteBuf)的等的讀寫 緩沖區(qū)自身的copy和slice 設(shè)置網(wǎng)絡(luò)字節(jié)序 ...
閱讀 566·2021-11-18 10:02
閱讀 1048·2021-11-02 14:41
閱讀 674·2021-09-03 10:29
閱讀 1893·2021-08-23 09:42
閱讀 2728·2021-08-12 13:31
閱讀 1199·2019-08-30 15:54
閱讀 1952·2019-08-30 13:09
閱讀 1427·2019-08-30 10:55