<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
上一小節簡單分析了PooledByteBufAllocator中, 執行緒區域性快取和arean的相關邏輯, 這一小節簡單分析下directArena分配緩衝區的相關過程
protected ByteBuf newDirectBuffer(int initialCapacity, int maxCapacity) { PoolThreadCache cache = threadCache.get(); PoolArena<ByteBuffer> directArena = cache.directArena; ByteBuf buf; if (directArena != null) { buf = directArena.allocate(cache, initialCapacity, maxCapacity); } else { if (PlatformDependent.hasUnsafe()) { buf = UnsafeByteBufUtil.newUnsafeDirectByteBuf(this, initialCapacity, maxCapacity); } else { buf = new UnpooledDirectByteBuf(this, initialCapacity, maxCapacity); } } return toLeakAwareBuffer(buf); }
獲取了directArena物件之後, 通過allocate方法分配一個ByteBuf, 這裡allocate方法是PoolArena類中的方法
跟到allocate方法中:
PooledByteBuf<T> allocate(PoolThreadCache cache, int reqCapacity, int maxCapacity) { PooledByteBuf<T> buf = newByteBuf(maxCapacity); allocate(cache, buf, reqCapacity); return buf; }
首先通過newByteBuf獲得一個ByteBuf物件
再通過allocate方法進行分配, 這裡要注意, 這裡進行分配的時候是執行緒私有的directArena進行分配
因為是directArena呼叫的newByteBuf, 所以這裡會進入DirectArena類的newByteBuf中:
protected PooledByteBuf<ByteBuffer> newByteBuf(int maxCapacity) { if (HAS_UNSAFE) { return PooledUnsafeDirectByteBuf.newInstance(maxCapacity); } else { return PooledDirectByteBuf.newInstance(maxCapacity); } }
因為預設通常是有unsafe物件的, 所以這裡會走到這一步中PooledUnsafeDirectByteBuf.newInstance(maxCapacity)
通過靜態方法newInstance建立一個PooledUnsafeDirectByteBuf物件
跟到newInstance方法中:
static PooledUnsafeDirectByteBuf newInstance(int maxCapacity) { PooledUnsafeDirectByteBuf buf = RECYCLER.get(); buf.reuse(maxCapacity); return buf; }
這裡通過RECYCLER.get()這種方式拿到一個ByteBuf物件, RECYCLER其實是一個物件回收站, 這部分內容會在後面的內容中詳細剖析, 這裡我們只需要知道, 這種方式能從回收站中拿到一個物件, 如果回收站裡沒有相關物件, 則建立一個新
因為這裡有可能是從回收站中拿出的一個物件, 所以通過reuse進行復用
final void reuse(int maxCapacity) { maxCapacity(maxCapacity); setRefCnt(1); setIndex0(0, 0); discardMarks(); }
這裡設定了的最大可擴容記憶體, 物件的參照數量, 讀寫指標位置都重置為0, 以及讀寫指標的位置標記也都重置為0
我們回到PoolArena的allocate方法中:
PooledByteBuf<T> allocate(PoolThreadCache cache, int reqCapacity, int maxCapacity) { PooledByteBuf<T> buf = newByteBuf(maxCapacity); allocate(cache, buf, reqCapacity); return buf; }
拿到了ByteBuf物件, 就可以通過allocate(cache, buf, reqCapacity)方法進行記憶體分配了
private void allocate(PoolThreadCache cache, PooledByteBuf<T> buf, final int reqCapacity) { //規格化 final int normCapacity = normalizeCapacity(reqCapacity); if (isTinyOrSmall(normCapacity)) { int tableIdx; PoolSubpage<T>[] table; //判斷是不是tinty boolean tiny = isTiny(normCapacity); if (tiny) { // < 512 //快取分配 if (cache.allocateTiny(this, buf, reqCapacity, normCapacity)) { return; } //通過tinyIdx拿到tableIdx tableIdx = tinyIdx(normCapacity); //subpage的陣列 table = tinySubpagePools; } else { if (cache.allocateSmall(this, buf, reqCapacity, normCapacity)) { return; } tableIdx = smallIdx(normCapacity); table = smallSubpagePools; } //拿到對應的節點 final PoolSubpage<T> head = table[tableIdx]; synchronized (head) { final PoolSubpage<T> s = head.next; //預設情況下, head的next也是自身 if (s != head) { assert s.doNotDestroy && s.elemSize == normCapacity; long handle = s.allocate(); assert handle >= 0; s.chunk.initBufWithSubpage(buf, handle, reqCapacity); if (tiny) { allocationsTiny.increment(); } else { allocationsSmall.increment(); } return; } } allocateNormal(buf, reqCapacity, normCapacity); return; } if (normCapacity <= chunkSize) { //首先在快取上進行記憶體分配 if (cache.allocateNormal(this, buf, reqCapacity, normCapacity)) { //分配成功, 返回 return; } //分配不成功, 做實際的記憶體分配 allocateNormal(buf, reqCapacity, normCapacity); } else { //大於這個值, 就不在快取上分配 allocateHuge(buf, reqCapacity); } }
這裡看起來邏輯比較長, 其實主要步驟分為兩步
對應步驟是:
cache.allocateTiny(this, buf, reqCapacity, normCapacity)
cache.allocateSmall(this, buf, reqCapacity, normCapacity)
cache.allocateNormal(this, buf, reqCapacity, normCapacity)
對應步驟是
allocateNormal(buf, reqCapacity, normCapacity)
在這裡對幾種型別的記憶體進行介紹:
之前的小節我們介紹過, 緩衝區記憶體型別分為tiny, small, 和normal, 其實還有種不常見的型別叫做huge, 那麼這幾種型別的記憶體有什麼區別呢, 實際上這幾種型別是按照緩衝區初始化空間的範圍進行區分的, 具體區分如下:
tiny
型別對應的緩衝區範圍為0-512B
small
型別對應的緩衝區範圍為512B-8K
normal
型別對應的緩衝區範圍為8K-16MB
huge
型別對應緩衝區範圍為大於16MB
簡單介紹下有關範圍的含義:
16MB對應一個chunk, netty是以chunk為單位向作業系統申請記憶體的
8k對應一個page, page是將chunk切分後的結果, 一個chunk對應2048個page
8k以下對應一個subpage, subpage是page的切分, 一個page可以切分多個subpage, 具體切分幾個需要根據subpage的大小而定, 比如只要分配1k的緩衝區, 則會將page切分成8個subpage
以上就是directArena記憶體分配的大概流程和相關概念,更多關於Netty分散式ByteBuf directArena分配緩衝區的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45