精品欧美一区二区三区在线观看 _久久久久国色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技術棧公眾號

裸体一区二区三区| 在线成人动漫av| 天堂网在线观看国产精品| 欧美中文字幕一区| 女女同性女同一区二区三区按摩| 国产露脸无套对白在线播放| 欧美国产高清| 精品一区电影国产| 日本77777| 精品极品在线| 国产精品国产自产拍高清av王其| 91免费版黄色| 欧美一区二区三区网站| 中文字幕一区二区三区乱码图片| 亚洲成人av在线播放| 成年人视频在线免费| 国产成人午夜| 久久久久免费观看| 97久久精品午夜一区二区| 亚洲视频 欧美视频| 99久久久久久久久| 哺乳一区二区三区中文视频| 一本久道中文字幕精品亚洲嫩| 一区二区三区av| 三级视频在线| 成人午夜免费av| 国产精品国模在线| 日韩三级视频在线| 亚洲综合色网| 丝袜美腿亚洲一区二区| 水蜜桃av无码| 亚洲精品在线国产| 欧美日韩大陆在线| 日本爱爱免费视频| 日韩激情电影免费看| 亚洲精品免费看| 伊甸园精品99久久久久久| 欧洲毛片在线| 99riav久久精品riav| 99re在线视频观看| 国产精品视频第一页| 青娱乐精品视频| 国产盗摄xxxx视频xxx69| 四虎成人精品永久免费av| 欧美一区二区三区另类| 中文字幕亚洲一区| 中文字幕有码在线播放| 蜜桃tv一区二区三区| 精品久久久久久久久久久久久久久 | 欧美6一10sex性hd| 国产精品久久国产精麻豆99网站| 精品国产综合久久| 国产黄色美女视频| 久久99精品国产91久久来源| 日韩av免费在线| 日韩精品一区二区在线播放| 一区二区国产在线| 一区二区三区视频免费| 国产美女喷水视频| 美女一区2区| 亚洲欧美综合国产精品一区| 欧美日韩国产综合一区二区| www黄色日本| 国精产品一区| 亚洲少妇最新在线视频| 神马影院午夜我不卡影院| 毛片免费在线| 国产校园另类小说区| 麻豆av一区二区| 天堂网2014av| 99久久99久久久精品齐齐| 成人在线看片| 午夜精品久久久久久久第一页按摩 | 美国av一区二区| 国产精品第七十二页| 日日噜噜噜噜人人爽亚洲精品| 亚洲激精日韩激精欧美精品| 欧美激情a在线| 久久精品免费在线| 亚洲欧洲一区二区天堂久久| 亚洲91精品在线| 日韩黄色精品视频| aⅴ色国产欧美| 欧美大荫蒂xxx| 国产性xxxx高清| 极品中文字幕一区| 97国产精品久久| 在线观看免费av片| 天堂av在线一区| 国产欧美日韩中文字幕在线| 国产一区二区三区视频免费观看| 九一九一国产精品| 97se亚洲综合| 偷拍精品一区二区三区| 久久久久久夜精品精品免费| 日韩精品久久一区| 成人午夜在线影视| 亚洲国产aⅴ成人精品无吗| 国产不卡一区二区视频| 精品人妻伦一二三区久| 另类专区亚洲| 51精品秘密在线观看| 日本女人性视频| 欧美丝袜足交| 中文在线不卡视频| 精品国产欧美日韩不卡在线观看| 国内揄拍国内精品久久| 奇米影视亚洲狠狠色| 伊人久久成人网| 国产乱人伦偷精品视频免下载| 国产精品对白一区二区三区| 亚洲经典一区二区三区| 91在线视频播放| 婷婷亚洲婷婷综合色香五月| av在线免费网站| 欧美日韩免费区域视频在线观看| 国产女大学生av| 91精品国产一区二区在线观看| 日韩精品一区二区三区中文不卡| 污污内射在线观看一区二区少妇| 色97色成人| 91精品国产91久久久久| 一区不卡在线观看| 99久久精品国产一区| 亚洲图片小说在线| 成年女人在线看片| 欧美日韩激情一区二区三区| 在线观看av中文字幕| 欧美疯狂party性派对| 久久久久久久久久久免费| 国产美女www爽爽爽| 成+人+亚洲+综合天堂| 日韩和欧美的一区二区| rebdb初裸写真在线观看| 欧美视频在线观看一区二区| 精品视频站长推荐| 91精品国产乱码久久久久久久| 欧美中文在线观看国产| 精品人妻一区二区三区蜜桃| 日本一二三四高清不卡| 日韩欧美国产综合在线| 精品国产亚洲一区二区三区在线 | 无码精品黑人一区二区三区| 电影一区二区三区久久免费观看| 日本电影亚洲天堂一区| 久久免费精品国产| 一区二区中文| 国产日产久久高清欧美一区| 日韩欧美在线观看一区二区| 夜夜精品视频一区二区| 岛国av免费在线| 加勒比久久综合| 久久久人成影片一区二区三区| www视频在线| 亚洲欧美日韩一区| 视频免费1区二区三区| 日韩欧美精品| 国产精品私拍pans大尺度在线 | 久草在线中文最新视频| 日韩美女天天操| 东方av正在进入| 黄色精品一二区| 亚洲一二三区精品| 精品乱码一区二区三区四区| 伊人久久久久久久久久| 久久久蜜桃一区二区| 26uuu欧美| 超碰网在线观看| 亚洲日产av中文字幕| 欧美在线视频一区二区| 日本高清视频在线| 午夜精品国产更新| 日韩av一二区| 久热综合在线亚洲精品| 日本亚洲欧洲精品| 全球最大av网站久久| 亚洲天堂成人在线| 亚洲免费视频二区| 中文字幕一区av| www.午夜av| 亚洲图片在线| 久久资源av| 成人自拍视频网| 日韩在线观看网址| 国产婷婷在线视频| 亚洲成人av免费| 色欲狠狠躁天天躁无码中文字幕| 玖玖视频精品| 中文字幕一区二区三区最新| av日韩一区| 久久av在线看| 国产成人免费观看网站| 欧美大片1688| 亚洲久久久久久久久久| 超碰在线免费97| 亚洲日本va在线观看| 国偷自产av一区二区三区麻豆| 亚洲午夜一级| 国产伦精品一区二区三区四区视频| 99久久精品免费看国产小宝寻花| 日韩精品免费电影| 亚洲中文一区二区三区| 国产精品伦理一区二区| 亚洲成年人av| 日韩电影一二三区| 在线视频亚洲自拍| 精品精品精品| 91精品久久久久久综合乱菊 | 日韩一区在线播放| 视频免费在线观看| 奇米色一区二区| 欧美一区二区视频在线播放| 伊人精品一区| 97久久人人超碰caoprom欧美| av伦理在线| 日韩视频一区在线| 日本福利在线观看| 91精选在线观看| 亚洲视频 欧美视频| 亚洲精品国产精品乱码不99| 久久精品成人av| 国产成人小视频| 亚洲高清在线免费观看| 在线免费高清一区二区三区| 日本一区二区三不卡| 亚洲亚洲一区二区三区| 欧美亚洲第一页| 日本中文字幕在线观看| 欧美精品一区二区三区高清aⅴ | 玖玖爱在线观看| 国产精品一二二区| www午夜视频| 欧美专区18| 你真棒插曲来救救我在线观看| 成人亚洲一区二区| 快播亚洲色图| 大香伊人久久精品一区二区| 91久久久国产精品| 日韩不卡在线| 欧美在线视频一区二区| 久久99亚洲网美利坚合众国| 日韩在线观看免费av| 麻豆传媒一区二区| 成人福利视频| 欧美激情亚洲综合一区| 黄网页在线观看| 中文字幕一区二区精品| 人操人视频在线观看| 精品国产麻豆免费人成网站| 精品国产乱码久久久久久蜜臀网站| 欧美色综合网站| 老熟妇仑乱一区二区av| 午夜欧美在线一二页| 麻豆changesxxx国产| 成人欧美一区二区三区1314| 国产精品视频在| 国产精品免费aⅴ片在线观看| 欧美图片第一页| 不卡的av网站| 亚洲黄色在线网站| 91蝌蚪porny| 大地资源二中文在线影视观看| 成人av资源在线观看| 中文字幕人妻熟女人妻a片| 国产一区二三区| 三级av免费看| 国产一区二区网址| 超碰在线超碰在线| 精彩视频一区二区| 成年人网站av| 国产成人综合在线播放| 中文字幕永久免费| 国产乱人伦偷精品视频不卡 | 婷婷伊人五月天| 国产精品毛片大码女人| 日本黄色录像视频| 亚洲欧美一区二区不卡| 欧美国产精品一二三| 亚洲在线观看免费视频| 日韩黄色精品视频| 色综合天天在线| 做爰视频毛片视频| 欧美猛男超大videosgay| 国产精品视频无码| 精品国产一区二区三区久久久蜜月| 亚洲国产成人一区二区| 亚洲国产婷婷香蕉久久久久久| 四虎影视在线观看2413| 亚洲天堂av网| 国精产品一区| 欧美国产日韩一区| 欧美电影网站| 国产欧美精品一区二区三区介绍| 电影91久久久| 92福利视频午夜1000合集在线观看| 精品一区二区三区免费看| 福利视频久久| 久久99国产精品视频| 欧美精品一区二区三区视频| 永久免费看片直接| 亚洲主播在线播放| 一级做a爰片久久毛片| 555夜色666亚洲国产免| 你懂的网站在线| 一区二区三区视频免费在线观看| 最近中文字幕免费mv2018在线| 97高清免费视频| 欧美经典影片视频网站| 国内精品二区| 久久免费大视频| 亚洲不卡中文字幕无码| 蜜桃视频在线一区| 免费不卡的av| 国产精品青草综合久久久久99| 日本最新中文字幕| 欧美美女直播网站| 欧美婷婷久久五月精品三区| 久久亚洲综合国产精品99麻豆精品福利| 欧美性受ⅹ╳╳╳黑人a性爽| 国产成人在线视频| 波多野结衣欧美| 亚洲精品中文字幕在线| 国产精品久久久久久模特| 欧美日韩精品区别| 久久亚洲精华国产精华液| 波多野结衣在线网址| 一本大道av伊人久久综合| 最新中文字幕第一页| 日韩高清免费观看| 91精选在线| 国产美女精彩久久| 妖精视频一区二区三区| 咪咪色在线视频| 蜜桃一区二区三区在线观看| 国产国语性生话播放| 夜夜爽夜夜爽精品视频| 91精品在线视频观看| 亚洲精品中文字幕av| 国产又色又爽又黄刺激在线视频| 成人免费网视频| 精品香蕉视频| 精品中文字幕av| 成人毛片在线观看| 青青草手机在线观看| 欧美片网站yy| 波多野结衣在线影院| 青青久久av北条麻妃海外网| 超碰在线亚洲| 精品人妻人人做人人爽| 国产一区二区毛片| 小泽玛利亚一区二区免费| 欧美片网站yy| 二区在线视频| 国产乱肥老妇国产一区二 | 欧美一二三在线| 成人不用播放器| 成人网在线免费看| 日韩一区二区三区免费播放| 一区二区成人网| 国产欧美日韩另类一区| 波多野结衣毛片| 亚洲免费电影在线观看| 亚洲图片另类小说| 亚洲欧美视频在线观看| 国产又爽又黄免费软件| 日韩亚洲欧美成人| 成人豆花视频| 菠萝蜜视频在线观看入口| 丰满少妇久久久久久久| 国产精品999久久久| 精品电影一区二区三区| 高清精品在线| 久久99精品久久久久久三级| 亚洲人体偷拍| 鲁大师私人影院在线观看| 一本色道a无线码一区v| 国产三区四区在线观看| 国产精品视频在线播放| 国产精品成人一区二区不卡| 337p日本欧洲亚洲大胆张筱雨| 亚洲国产aⅴ天堂久久| 青梅竹马是消防员在线| 国产精品嫩草影院一区二区| 久久精品免费一区二区三区| 性久久久久久久久久久久久久| 亚洲成av人片在线| 麻豆导航在线观看| 成人黄色影片在线| 国产一区美女| 精品少妇人妻一区二区黑料社区| 欧美色视频在线观看| yellow91字幕网在线| 国产精品制服诱惑| 久久高清国产| 国产视频精品免费| 日韩精品自拍偷拍| 小明成人免费视频一区| 男人j进女人j| 91麻豆国产在线观看| 中文字幕日韩国产|