精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

使用堆內內存HeapByteBuffer的注意事項

存儲 存儲軟件
本文介紹了在文件 IO 中使用 HeapByteBuffer 的注意事項,需要考慮到 FileChannel 內部的復制問題,意識到這一過程會有堆外內存的復制開銷。

[[427434]]

本文轉載自微信公眾號「Kirito的技術分享」,作者kiritomoe。轉載本文請聯系Kirito的技術分享公眾號。

前言

國慶假期一眨眼就過去了,本來在家躺平的很舒服,沒怎么肝云原生編程挑戰賽,傳送門:https://tianchi.aliyun.com/s/8bf1fe4ae2aea736e692c31c6952042d ,偏偏對手們假期開始卷起來了,眼看就要被人反超了,嚇得我趕緊繼續優化了。比賽大概還有一個月才結束,Kirito 的詳細方案也會在比賽結束后分享,這期間我會分享一些比賽中的一些通用優化或者細節知識點,例如本文就是這么一個例子。

趁著假期最后一天,分享一個很多人容易踩的一個坑:HeapByteBuffer 的使用問題。我們都知道 NIO 分裝了 ByteBuffer 接口,使得 filechannel 的文件 IO API 變得非常的簡單。ByteBuffer 主要有兩個實現類

  • HeapByteBuffer 堆內內存
  • DirectByteBuffer 堆外內存

按我的個人經驗,大多數情況,無論是讀操作還是寫操作,我都傾向于使用 DirectByteBuffer,主要是因為 HeapByteBuffer 在和 FileChannel 交互時,可能會有一些出乎大家意料的內部操作,也就是這篇文章的標題中提到的注意事項,這里先賣個關子。

先來看看這次比賽為什么要用到 HeapByteBuffer 呢?

原因一:賽題需要設計分級存儲,并且提供了 6G 堆內內存 + 2G 堆外內存,一個最直接的思路便是使用內存來存儲熱點數據,而內存存儲數據最方便的數據結構便是 ByteBuffer 了。

原因二:由于堆內 6G 遠大于堆外 2G,且 JVM 參數不能調整,所以要想利用好堆內富余的內存去做緩存,非 HeapByteBuffer 莫屬了。

可能有一些讀者并沒有關注賽題,我這里簡化一下前言,可以直接理解為:有一塊 2G 的 HeapByteBuffer 用于文件 IO,我們該如何利用。

HeapByteBuffer 的復制問題

廢話不多說,直接來看 HeapByteBuffer 的坑在哪兒。

使用代碼描述 HeapByteBuffer 的文件 IO 操作,大概率會寫出如下的代碼:

  1. public void readInOneThread() throws Exception { 
  2.     int bufferSize = 50 * 1024 * 1024; 
  3.     File file = new File("/essd"); 
  4.     FileChannel fileChannel = new RandomAccessFile(file, "rw").getChannel(); 
  5.     ByteBuffer byteBuffer = ByteBuffer.allocate(bufferSize); 
  6.     fileChannel.read(byteBuffer); 

上述的代碼,將文件中的數據緩存到了內存中,無論是賽題還是生產場景,這個行為通常都是多線程的,例如在云原生編程挑戰賽的評測下,有 40 個線程進行讀寫,如果按照線程維度進行緩存,每個線程分到 50M 用于內存緩存自然是沒有問題。

而如果你直接使用上述代碼,在評測中可能會直接得到內存溢出相關的異常。其實我在之前堆外內存泄漏的文章中也提到過這個問題,不過角度有所不同。原因很簡單,直接來看源碼。

FileChannel 使用的是 IOUtil 進行讀寫操作

  1. static int read(FileDescriptor var0, ByteBuffer var1, long var2, NativeDispatcher var4) throws IOException { 
  2.     if (var1.isReadOnly()) { 
  3.         throw new IllegalArgumentException("Read-only buffer"); 
  4.     } else if (var1 instanceof DirectBuffer) { 
  5.         return readIntoNativeBuffer(var0, var1, var2, var4); 
  6.     } else { 
  7.         ByteBuffer var5 = Util.getTemporaryDirectBuffer(var1.remaining()); 
  8.         int var7; 
  9.         try { 
  10.             int var6 = readIntoNativeBuffer(var0, var5, var2, var4); 
  11.             var5.flip(); 
  12.             if (var6 > 0) { 
  13.                 var1.put(var5); 
  14.             } 
  15.             var7 = var6; 
  16.         } finally { 
  17.             Util.offerFirstTemporaryDirectBuffer(var5); 
  18.         } 
  19.         return var7; 
  20.     } 

可以發現當使用 HeapByteBuffer 時,會走到下面這個分支

  1. Util.getTemporaryDirectBuffer(var1.remaining()); 

這個 Util 封裝了更為底層的一些 IO 邏輯

  1. package sun.nio.ch; 
  2. public class Util { 
  3.     private static ThreadLocal<Util.BufferCache> bufferCache; 
  4.      
  5.     public static ByteBuffer getTemporaryDirectBuffer(int var0) { 
  6.         if (isBufferTooLarge(var0)) { 
  7.             return ByteBuffer.allocateDirect(var0); 
  8.         } else { 
  9.             // FOUCS ON THIS LINE 
  10.             Util.BufferCache var1 = (Util.BufferCache)bufferCache.get(); 
  11.             ByteBuffer var2 = var1.get(var0); 
  12.             if (var2 != null) { 
  13.                 return var2; 
  14.             } else { 
  15.                 if (!var1.isEmpty()) { 
  16.                     var2 = var1.removeFirst(); 
  17.                     free(var2); 
  18.                 } 
  19.  
  20.                 return ByteBuffer.allocateDirect(var0); 
  21.             } 
  22.         } 
  23.     } 

isBufferTooLarge 這個方法會根據傳入 Buffer 的大小決定如何分配堆外內存,如果過大,直接分配大緩沖區;如果不是太大,會使用 bufferCache 這個 ThreadLocal 變量來進行緩存,從而復用(實際上這個數值非常大,幾乎不會走進直接分配堆外內存這個分支)。這么看來似乎發現了兩個不得了的結論:

使用 HeapByteBuffer 讀寫都會經過 DirectByteBuffer,寫入數據的流轉方式其實是:HeapByteBuffer -> DirectByteBuffer -> PageCache -> Disk,讀取數據的流轉方式正好相反。

使用 HeapByteBuffer 讀寫會申請一塊跟線程綁定的 DirectByteBuffer。這意味著,線程越多,臨時 DirectByteBuffer 就越會占用越多的空間。

根據這兩個結論,我們再回到賽題中,如果直接按照上述的方式進行讀寫,40 個線程每個都持有一個 50M 的堆內內存,同時又因為 IOUtil 的內部行為,額外分配了 40*50M 的堆外內存, 堆外內存在不經意間就被用光了!出現堆外內存溢出的異常也就不奇怪了。

為什么 HeapByteBuffer 在 IO 時需要復制到 DirectByteBuffer

這個我之前也介紹過,詳情可以參考我的一篇舊文:《一文探討堆外內存的監控與回收》。總結如下:

  • 為了方便 GC 的實現,DirectByteBuffer 指向的 native memory 是不受 GC 管轄的
  • HeapByteBuffer 背后使用的是 byte 數組,其占用的內存不一定是連續的,不太方便 JNI 方法的調用
  • 數組實現在不同 JVM 中可能會不同

解決方案

其實我們本質上是為了給每個線程維護一塊 HeapByteBuffer,用于緩存數據,并沒有必要以 ByteBuffer 的大小為維度來進行 IO。可以借鑒 IOUtil 中復制 DirectByteBuffer 的思路來優化這一過程。代碼示例如下:

  1. public void directBufferCopy() throws Exception { 
  2.     File file = new File("/essd"); 
  3.     FileChannel fileChannel = new RandomAccessFile(file, "rw").getChannel(); 
  4.     ByteBuffer byteBuffer = ByteBuffer.allocate(50 * 1024 * 1024); 
  5.     ByteBuffer directByteBuffer = ByteBuffer.allocateDirect(4 * 1024); 
  6.     for (int i = 0; i < 12800; i++) { 
  7.         directByteBuffer.clear(); 
  8.         fileChannel.read(directByteBuffer, i * 4 * 1024); 
  9.         directByteBuffer.flip(); 
  10.         byteBuffer.put(directByteBuffer); 
  11.     } 

在 Java 中,從磁盤到堆內內存,一定無法省略堆外內存的復制,但我們可以自己復制,從而使得這個過程更加直觀地被我們自己操控,而不是被 FileChannel 的內部邏輯左右。

這里也需要注意

單次 IO 使用的 DirectByteBuffer 不宜過大,僅僅作為一個運輸載體,起到一個運輸數據的作用。這樣在多線程場景下,才不至于占用過多的堆外內存

單次 IO 使用的 DirectByteBuffer 不宜過小,否則會出現讀寫放大的問題,一般建議設置 4kb 的整數倍,具體以實際測試結果為準。

其他注意事項

HeapByteBuffer 讀寫時的復制問題是本文的主角,但使用 HeapByteBuffer 作為緩存時,也需要注意一些其他問題。例如比賽場景中,你可能希望開辟一大塊 HeapByteBuffer,6G 堆內內存,分配個 4G 用作緩存總可以吧?可不可以我說了不算,你感興趣的話倒是可以測試一下是否可行,還需要考慮 GC 情況,需要綜合考慮老年代和新生代的配比,如果你分配了過多堆內內存給 HeapByteBuffer 緩存,可能會直接導致 OutOfMemory 或者觸發 GC。

同時,如果 HeapByteBuffer 占用了過多內存,留給操作系統的 PageCache 也會非常有限,這兩者使用的可是同一塊內存!如果你的程序利用到了 PageCache 的特性,可能會由于 PageCache 空間不夠,導致 IO 速度變慢。

總結

 

本文介紹了在文件 IO 中使用 HeapByteBuffer 的注意事項,需要考慮到 FileChannel 內部的復制問題,意識到這一過程會有堆外內存的復制開銷。在實際使用場景中,個人更加推薦直接使用 DirectByteBuffer 進行 IO 操作。如果出于某些原因,一定需要使用 HeapByteBuffer 存儲作為緩存,可以參考文中分批使用 DirectByteBuffer 進行 IO 并復制的方案。

 

責任編輯:武曉燕 來源: Kirito的技術分享
相關推薦

2010-11-26 16:27:01

MySQL使用變量

2012-03-12 16:46:22

NoSQL數據庫

2011-07-28 17:29:22

HBaseShell

2011-05-26 11:22:04

SEO

2011-07-25 17:48:10

iPhone 內存

2010-01-21 11:30:10

2011-07-19 10:16:58

噴墨打印機注意事項

2010-01-18 14:25:19

使用C++Builde

2011-07-21 15:40:24

iPhone 內存管理 對象

2013-09-25 10:15:51

閃存存儲優勢注意事項

2011-08-02 13:08:06

Oracle索引

2009-08-27 10:40:56

Java路徑

2010-07-20 13:02:03

SQL Server索

2011-07-26 18:43:34

HBase Shell

2011-04-14 11:28:07

光纖

2012-12-27 13:04:17

Android開發SQLite數據庫

2010-09-16 09:52:49

CSS display

2009-12-22 09:48:58

WCF枚舉類型

2009-12-15 17:47:17

VSIP

2011-08-04 15:00:46

AmoebaMySQL
點贊
收藏

51CTO技術棧公眾號

欧美码中文字幕在线| 都市激情综合| 99精品久久99久久久久| 欧美一区第一页| 国产熟女一区二区| 电影91久久久| 精品久久久久久久久久久久久久 | 影音先锋黄色网址| 欧美激情一区| 国产一区二区日韩| 日本少妇xxx| 亚洲天堂一区二区| 亚洲已满18点击进入久久| 日韩一区二区三区资源| 国产熟女一区二区三区四区| 玖玖精品视频| 欧美精品18videos性欧| 俄罗斯毛片基地| 欧美日日夜夜| 欧美一区二区三区四区五区| 成人一级片网站| 日韩精品亚洲人成在线观看| 久久精品男人天堂av| 99在线看视频| 国产毛片毛片毛片毛片| 美女日韩在线中文字幕| 欧美激情视频免费观看| 国产亚洲精品久久久久久豆腐| 日韩欧美黄色| 精品剧情v国产在线观看在线| 国产理论在线播放| 久久影院午夜精品| 亚洲成年人影院| 久久天天东北熟女毛茸茸| www.在线播放| 国产午夜亚洲精品羞羞网站| 激情伦成人综合小说| 午夜精品久久久久久久96蜜桃| 蜜桃视频免费观看一区| 欧美做受高潮电影o| 国产乡下妇女做爰毛片| 一区二区三区四区在线观看国产日韩| 最近2019中文字幕大全第二页| 懂色av粉嫩av蜜乳av| 亚洲一区二区电影| 欧美一级片免费看| 久久人人爽人人片| 经典三级久久| 日韩视频一区在线观看| 欧美熟妇另类久久久久久多毛| 2019中文亚洲字幕| 欧美丰满美乳xxx高潮www| 久久久久久久久久久久91| 欧美极品免费| 欧美亚州韩日在线看免费版国语版| 久久亚洲中文字幕无码| sm久久捆绑调教精品一区| 亚洲成人动漫av| 霍思燕三级露全乳照| 麻豆mv在线看| 一本久道中文字幕精品亚洲嫩| 日韩久久一级片| 日韩免费电影| 欧美视频在线观看一区二区| 亚洲精品久久久久久宅男| 日韩有码欧美| 日韩欧美电影一二三| japan高清日本乱xxxxx| 北条麻妃一区二区三区在线观看 | 欧美美乳在线| 国产偷国产偷精品高清尤物| 日韩一区不卡| 麻豆av免费在线观看| 亚洲美女免费视频| 成人性免费视频| 伊人久久综合一区二区| 欧美在线影院一区二区| 天天操精品视频| 91精品国产自产在线丝袜啪 | 91精品中文在线| www.国产三级| 99国产一区二区三精品乱码| 欧美日韩精品久久| 久久国产精品一区| 亚洲福利一区二区| 五月婷婷深爱五月| 日韩精品视频一区二区三区| 亚洲国产精品人人爽夜夜爽| 亚洲人成人无码网www国产 | 九色丨蝌蚪丨成人| 亚洲色图偷窥自拍| 曰本女人与公拘交酡| 国产偷自视频区视频一区二区| 国产成人自拍视频在线观看| 99er热精品视频| 9l国产精品久久久久麻豆| 日韩国产美国| 欧美1234区| 欧美性大战久久久| 国产高潮失禁喷水爽到抽搐 | 中文字幕精品在线播放| 人成在线免费网站| 91精品国产综合久久国产大片| 中文字幕精品久久久| 日本黄色精品| 97在线视频免费播放| 亚洲一区精品在线观看| 99久久99久久免费精品蜜臀| 中文字幕一区二区三区有限公司 | fc2成人免费视频| 欧美日韩伦理在线免费| 国外成人性视频| 国产一区二区波多野结衣| www.亚洲精品| 久久国产精品免费观看| 成人精品电影在线| 亚洲成色www8888| 日本中文字幕免费在线观看 | 一级黄色片在线免费观看| 国产不卡一二三区| 午夜精品视频在线| 精品人妻一区二区三区四区不卡 | 丁香六月综合激情| 伊人久久大香线蕉精品| 欧洲亚洲两性| 日韩激情视频在线| 国产中文字幕免费| 国产精品亚洲人在线观看| 亚洲精品一区二区三区蜜桃久| 大菠萝精品导航| 精品国产乱码久久久久久影片| 少妇视频一区二区| 久久99热国产| 亚洲精品成人三区| 成人做爰视频www| 亚洲激情在线观看| 久久中文字幕在线观看| 国内成人精品2018免费看| 亚洲在线不卡| 成人性片免费| 国产亚洲福利一区| www.欧美色| 久久久国产午夜精品| 国产综合av在线| 欧美爱爱网站| 91av在线影院| 天天射天天色天天干| 亚洲成av人影院| 免费不卡的av| 日韩视频一区| 美女被啪啪一区二区| 日本蜜桃在线观看视频| 日韩高清a**址| 天天做天天爱夜夜爽| 91香蕉视频mp4| 欧美视频第三页| 蜜桃视频欧美| 国产精品欧美日韩一区二区| 91最新在线| 欧美精品久久一区| 国产乱国产乱老熟300| 国产高清不卡二三区| 国产免费黄色一级片| 丁香5月婷婷久久| 91成人在线视频| 搞黄视频免费在线观看| 欧美日韩亚洲国产综合| 人人澡人人澡人人看| 国产91精品欧美| 男人用嘴添女人下身免费视频| 欧美亚洲色图校园春色| 国产91精品网站| 理论片午午伦夜理片在线播放| 7777精品久久久大香线蕉| a级黄色片免费看| 91日韩在线专区| 国产91色在线观看| 欧美在线看片| 麻豆av福利av久久av| 黄色成人在线视频| 欧美高清视频免费观看| 五月婷婷丁香花| 欧美日韩精品一区视频| 免费在线看黄网址| 久久久综合视频| 天堂在线一区二区三区| 日韩午夜激情| 中文字幕一区二区中文字幕| aaa国产精品视频| 国产97免费视| 50度灰在线| 亚洲欧美日韩一区在线| 国产精品主播一区二区| 五月天丁香久久| 亚洲女同二女同志奶水| 懂色av一区二区三区免费观看| 黄色片视频在线播放| 欧美黄色一区| 视频一区视频二区视频| 国产一区在线电影| 91精品在线播放| 五月天av在线| 色综合久综合久久综合久鬼88| 内衣办公室在线| 日韩区在线观看| 国产精品传媒在线观看| 亚洲h在线观看| 婷婷久久综合网| 国产三级精品视频| 国产香蕉精品视频| 久久aⅴ国产欧美74aaa| 国产v亚洲v天堂无码久久久| 欧美三级特黄| 一区二区三视频| 国产一区二区亚洲| 国产综合精品一区二区三区| 精品午夜视频| 国产精品视频一区二区三区四| 美女的胸无遮挡在线观看| 九九久久综合网站| 嫩草在线视频| 中文字幕在线成人| 国产黄在线观看免费观看不卡| 亚洲成人av在线播放| japanese国产| 91精品国产综合久久香蕉的特点| www.日韩一区| 色域天天综合网| 中文字幕在线字幕中文| 一级特黄大欧美久久久| 最新一区二区三区| 综合久久国产九一剧情麻豆| 国产成人免费观看网站| 久久久久久夜精品精品免费| 中文在线永久免费观看| 成人免费视频一区| 日本天堂在线播放| 白白色 亚洲乱淫| 精品少妇人妻av一区二区三区| 国产成人av电影在线观看| 在线播放黄色av| 国产一区欧美日韩| 欧美xxxxxbbbbb| 国产麻豆视频精品| 日韩精品――色哟哟| 国产精品亚洲专一区二区三区| 小早川怜子一区二区三区| 韩国女主播成人在线| 中文字幕在线综合| 精品一区二区三区免费观看| 午夜xxxxx| 高清日韩电视剧大全免费| 久久无码专区国产精品s| 国产成人精品免费在线| 日本wwwxx| 成人av在线资源网站| 国产性生活毛片| 久久久亚洲午夜电影| 无码少妇精品一区二区免费动态| 国产日产欧美一区| 登山的目的在线| 一区二区三区日韩精品视频| 国产精品a成v人在线播放| 午夜欧美在线一二页| 欧美在线观看不卡| 欧美性感一类影片在线播放| 国产精品无码在线播放| 精品国产制服丝袜高跟| 午夜18视频在线观看| 亚洲视频在线观看网站| 欧美三级黄网| 久久久久久国产三级电影| 多野结衣av一区| 国产精品av在线播放| 91成人精品观看| 国产精品一区二区欧美| 国产一区二区三区四区大秀| 黄频视频在线观看| 在线成人黄色| 538在线视频观看| 风间由美性色一区二区三区| 国产美女精品久久| 国产精品不卡视频| 日韩欧美大片在线观看| 欧美伊人久久久久久久久影院 | 五月天av影院| 亚洲人成免费| 日本在线播放一区二区| www.欧美.com| 懂色av粉嫩av浪潮av| 一区二区三区不卡视频在线观看| 国产成人在线视频观看| 4438x成人网最大色成网站| 无码国产伦一区二区三区视频| 最近2019好看的中文字幕免费| 青草在线视频在线观看| 国产精品99久久久久久久久| 日韩一二三区| 亚洲成人午夜在线| 亚洲精品视频啊美女在线直播| 鲁一鲁一鲁一鲁一av| 成人不卡免费av| 中文国语毛片高清视频| 一本大道av伊人久久综合| 国产91麻豆视频| 少妇高潮 亚洲精品| 免费成人在线电影| 99在线高清视频在线播放| 欧美激情成人| 麻豆av免费在线| 成人国产精品视频| 免费高清在线观看电视| 欧美在线观看视频一区二区三区| 蜜臀av在线观看| 久久影视免费观看| 日本精品网站| 欧美日韩国产高清视频| 亚洲成人中文| 国产精品久久久久久久99| 国产欧美日韩另类视频免费观看| 日韩成人av毛片| 欧美成人三级电影在线| 米奇精品一区二区三区| 国产精品久久久久久久午夜| 天堂99x99es久久精品免费| 日本免费a视频| 国产精品一品二品| 91精品国产闺蜜国产在线闺蜜| 欧美亚洲高清一区二区三区不卡| 欧美女同网站| 日本久久中文字幕| 免费成人av| 中文字幕日本最新乱码视频| av电影在线观看不卡| 精品在线视频免费观看| 日韩欧美国产一区二区三区 | 日本免费网站在线观看| 欧美大荫蒂xxx| 亚洲精品观看| 男女激烈动态图| 国产精品性做久久久久久| 全网免费在线播放视频入口 | 性感美女福利视频| 97久久超碰福利国产精品…| 粉嫩的18在线观看极品精品| 国产成a人亚洲精v品在线观看| 国产精品18久久久| 国产性一乱一性一伧一色| 欧美不卡一区二区三区四区| 污视频网站免费在线观看| 99re国产在线播放| 欧美日韩一区二区国产| 亚洲色偷偷色噜噜狠狠99网| 精品久久久久久久久中文字幕 | 国产精品久久国产精麻豆99网站| 国产精品传媒在线观看| 综合136福利视频在线| 91丨精品丨国产| 久久久99精品视频| 成人黄色a**站在线观看| 欧美一级片免费在线观看| 永久免费精品影视网站| 色8久久久久| 亚洲精品国产suv一区88| www.日韩大片| 亚洲中文一区二区| 俺去亚洲欧洲欧美日韩| 日韩一级淫片| 北条麻妃在线视频观看| 国产调教视频一区| 国产日韩欧美中文字幕| 久久久久久久久久久久av| 九热爱视频精品视频| 爱爱爱爱免费视频| 亚洲一区二区免费视频| 亚洲色图21p| 成人高清视频观看www| 合欧美一区二区三区| 六月婷婷七月丁香| 制服丝袜亚洲色图| 国产直播在线| 亚洲v国产v在线观看| 国产成人在线看| www五月天com| 麻豆乱码国产一区二区三区| 精品国产午夜肉伦伦影院| 一路向西2在线观看| 亚洲一区中文日韩| www亚洲人| 国精产品一区二区| 精品在线免费观看| 久久久久久久久久免费视频| 原创国产精品91| 国产精品午夜av| 91亚洲精品久久久蜜桃借种| 香蕉久久一区二区不卡无毒影院| av色图一区| 久久精品国产综合精品| 激情综合网最新| 神马久久久久久久|