Netty源碼分析第5章(ByteBuf)----第5節: directArena分配緩沖區概述

Netty源碼分析第5章(ByteBuf)---->第5節: directArena分配緩沖區概述

?

Netty源碼分析第五章: ByteBuf

?

第五節:?directArena分配緩沖區概述

?

上一小節簡單分析了PooledByteBufAllocator中, 線程局部緩存和arean的相關邏輯, 這一小節簡單分析下directArena分配緩沖區的相關過程

回到newDirectBuffer中:

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進行分配

我們跟到newByteBuf方法中

因為是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進行復用

跟到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)方法進行內存分配了

跟到allocate方法中:

private void allocate(PoolThreadCache cache, PooledByteBuf<T> buf, final int reqCapacity) {//規格化final int normCapacity = normalizeCapacity(reqCapacity);if (isTinyOrSmall(normCapacity)) { int tableIdx;PoolSubpage<T>[] table;//判斷是不是tintyboolean tiny = isTiny(normCapacity);if (tiny) { // < 512//緩存分配if (cache.allocateTiny(this, buf, reqCapacity, normCapacity)) {return;}//通過tinyIdx拿到tableIdxtableIdx = 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);}
}

這里看起來邏輯比較長, 其實主要步驟分為兩步

1.首先在緩存上進行分配, 對應步驟是:

? cache.allocateTiny(this, buf, reqCapacity, normCapacity)

? cache.allocateSmall(this, buf, reqCapacity, normCapacity)

? cache.allocateNormal(this, buf, reqCapacity, normCapacity)

2.如果在緩存上分配不成功, 則實際分配一塊內存, 對應步驟是

? 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內存分配的大概流程和相關概念

?

上一節: PooledByteBufAllocator簡述

下一節: 命中緩存的分配

?

posted on 2019-01-01 18:32 向南是個萬人迷 閱讀(...) 評論(...) 編輯 收藏

轉載于:https://www.cnblogs.com/xiangnan6122/p/10205478.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/248736.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/248736.shtml
英文地址,請注明出處:http://en.pswp.cn/news/248736.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

uni-app(從零開始)

uni-app&#xff08;從零開始&#xff09; uni-app 是什么&#xff1f; uniapp 就是使用Vue.js技術開發所有前端框架的跨端框架uniapp 就是可以將一套代碼 發布到多個平臺 uniapp 和 Vue 的關系&#xff1f; uniapp是基于vue進行開發&#xff0c;繼承了Vue的特性和語法在開…

Remote desktop manager共享賬號

因為多個遠程機器&#xff0c;是會用了域賬號進行登錄的。而域賬號的密碼&#xff0c;三個月之后&#xff0c;密碼強制過期 添加一個新的entry&#xff0c;類型是Credential Entry&#xff0c;然后選擇用戶名/密碼 在remote desktop編輯的頁面&#xff0c;Credentials選擇Crede…

bzoj4403:序列統計

我好傻啊 題目 先來看看長度只能為\(n\)的情況 那么答案非常顯然是\(\binom{mn-1}{n}\) 其中\(mR-L1\) 因為我們要構造一個非降序列&#xff0c;顯然可能一個數會被選擇多次&#xff0c;組合非常不好做&#xff0c;于是我們可以把每一個數的下標加上其對應的下標那么現在的值域…

Mui常用的方法

中對話框 語法&#xff1a;mui.confirm 用法 mui.confirm("確認要切換角色&#xff1f;", "提示", btnArray, function(e) {if(e.index 1) {} else {}});組件名作用alert警告框confirm確認框prompt輸入對話框toast消息提示框&#xff08;自動消失&#x…

sudo: pip:找不到命令

https://blog.csdn.net/fcku_88/article/details/84191288轉載于:https://www.cnblogs.com/xxswkl/p/11012709.html

java ListMapString,Object遍歷的方法

java List<Map<String,Object>遍歷的方法 public class Test {public static void main(String[] args) {List<Map<String, Object>> listMaps new ArrayList<Map<String, Object>>();Map<String, Object> map1 new HashMap<Strin…

vue如何更換網頁標簽的logo

Vue2 版本更換圖標 在我們項目的根目錄下面去添加或者替換 favicon.icon文件 找到我們的 build 文件夾下面的這兩個文件 進行如下配置 favicon: resolveApp(’./favicon.ico’) 刷新后發現并沒有什么效果 莫慌 最后一步 重啟項目 改變端口 如果重啟后還沒有起到作用的話就…

Java并發編程的藝術(十)——Java中的鎖(5)

1. LockSupport工具 1.1 LockSupport的作用 當需要阻塞或喚醒一個線程的時候&#xff0c;都會使用LockSupport工具類來完成相應工作。LockSupport定義了一組公共的靜態方法&#xff0c;這些方法提供了做基本的線程阻塞和喚醒功能。 1.2 LockSupport提供的阻塞和喚醒方法 方法描…

運動-模擬返回頂部

第一步&#xff1a;獲取底部的那個按鈕對象&#xff0c;默認的情況下那個按鈕對象是不可見的。可見的條件的是滾輪距離頂部有距離。 var oBtndocument.getElementById(btn1); 第二步&#xff1a;添加滾輪事件。 (1). 獲取滾輪距離頂部的距離。如果距離大于0&#xff0c;就將按鈕…

《JavaScript高級程序設計》筆記總結

在北京上班的我每天在上下班路上的時間總共是兩個半小時&#xff0c;為了充實這兩個多小時的時間&#xff0c;我便花了銀子換得了下面這個寶貝 本書內容&#xff08;引用書中前言&#xff09; 本書提供了JavaScript開發人員必須掌握的內容&#xff0c;全面涵蓋了JavaScript的…

Task執行多次

項目中&#xff0c;曾經出現過啟動時數據庫連接數瞬間增大&#xff0c;當時并沒有注意該問題。 后期&#xff0c;由于Task任務多次執行&#xff0c;才著手查看這個問題&#xff0c;經排查&#xff0c;由于tomcat中webapp配置多次&#xff0c;導致webapp被掃描多次&#xff08;配…

ES6 的新特性總結

ES6 的新特性總結 關于聲明變量 由 var 變成 let 和 const 區別&#xff1a; var聲明的變量會掛載到window上&#xff0c;let和const聲明的變量不會var聲明的變量存在變量提升&#xff0c;而let和const聲明的變量不存在變量提升let和const聲明的變量形成塊級作用域在同一作…

遞推(一):遞推法的基本思想

所謂遞推&#xff0c;是指從已知的初始條件出發&#xff0c;依據某種遞推關系&#xff0c;逐次推出所要求的各中間結果及最后結果。其中初始條件或是問題本身已經給定&#xff0c;或是通過對問題的分析與化簡后確定。 利用遞推算法求問題規模為n的解的基本思想是&#xff1a;當…

在vue中methods互相調用的方法

在vue中methods互相調用的方法 轉載于:https://www.cnblogs.com/macT/p/10212878.html

MUI H5+ 開發app基礎

加載子頁面(防止手機性能差,出現上下滑動卡頓) 其中 url 就是子頁面的路徑 id 為自定義 通常和頁面名稱一致頁面的跳轉和傳值 切記 如果使用mui組件內的底部導航跳轉的方式只能使用document獲取元素的id 頁面跳轉傳值 新頁面接收參數 頁面初始化 H5加載完畢 判斷某個元素中是…

對象

一、對象 <!DOCTYPE html> <html><head><meta charset"UTF-8"><title></title><script type"text/javascript">/** JS中數據類型* String 字符串* Number 數值* Boolean 布爾值* Null 空值* Undefine…

uni-app 組件傳值

uni-app中的組件之間的傳值 我們將compontents中的test文件作為子組件 引入到index中使用 引入并使用 效果如下 父傳子 首先我們在父組件中使用子組件的標簽中去自定義title 在子組件中 通過props去接收并處理 效果如下&#xff1a; 子傳父 子組件中 設置一個按鈕…

JSP XML數據處理

JSP XML數據處理 當通過HTTP發送XML數據時&#xff0c;就有必要使用JSP來處理傳入和流出的XML文檔了&#xff0c;比如RSS文檔。作為一個XML文檔&#xff0c;它僅僅只是一堆文本而已&#xff0c;使用JSP創建XML文檔并不比創建一個HTML文檔難。 使用JSP發送XML 使用JSP發送XML內容…

Docker 圖形界面管理工具 -- Portainer

Portainer&#xff08;基于 Go&#xff09;是一個輕量級的管理界面&#xff0c;可讓您輕松管理Docker主機或Swarm集群。 Portainer的使用意圖是簡單部署。它包含可以在任何 Docker 引擎上運行的單個容器&#xff08;Docker for Linux 和 Docker for Windows&#xff09;。 Port…

vue cli3.0創項目報錯‘This may cause things to work incorrectly. Make sure to use the same version for b’

錯誤&#xff1a; throw new Error(^Error:Vue packages version mismatch:- vue2.6.12 (C:\Users\Administrator\AppData\Roaming\npm\node_modules\vue\dist\vue.runtime.common.js) - vue-template-compiler2.6.11 (C:\Users\Administrator\AppData\Roaming\npm\node_module…