乐鱼百家乐博彩平台游戏活动_使用堆内内存HeapByteBuffer的提防事项

发布日期:2023-10-30 06:12    点击次数:53

乐鱼百家乐博彩平台游戏活动_使用堆内内存HeapByteBuffer的提防事项

乐鱼百家乐博彩平台游戏活动_[[427434]]

本文转载自微信公众号「Kirito的本事共享」,作家kiritomoe。转载本文请策划Kirito的本事共享公众号。

欧博百家乐 绪论

国庆假期一眨眼就昔日了,底本在家躺平的很欢畅,没何如肝云原生编程挑战赛,传送门:https://tianchi.aliyun.com/s/8bf1fe4ae2aea736e692c31c6952042d ,偏巧敌手们假期开动卷起来了,眼看就要被东说念主反超了,吓得我速即络续优化了。比赛约略还有一个月才截止,Kirito 的详备决策也会在比赛截止后共享,这时候我会共享一些比赛中的一些通用优化或者细节学问点,举例本文就是这样一个例子。

趁着假期终末一天,共享一个许多东说念主容易踩的一个坑:HeapByteBuffer 的使用问题。咱们王人知说念 NIO 分装了 ByteBuffer 接口,使得 filechannel 的文献 IO API 变得终点的肤浅。ByteBuffer 主要有两个杀青类

HeapByteBuffer 堆内内存 DirectByteBuffer 堆外内存

按我的个东说念主警戒,大无数情况,无论是读操作如故写操作,我王人倾向于使用 DirectByteBuffer,主如果因为 HeapByteBuffer 在和 FileChannel 交互时,可能会有一些出乎天下意想的里面操作,也就是这篇著述的标题中提到的提防事项,这里先卖个关子。

乐鱼百家乐

先来望望此次比赛为什么要用到 HeapByteBuffer 呢?

皇冠体育hg86a

原因一:赛题需要缱绻分级存储,而且提供了 6G 堆内内存 + 2G 堆外内存,一个最径直的念念路即是使用内存来存储热门数据,而内存存储数据最便捷的数据结构即是 ByteBuffer 了。

原因二:由于堆内 6G 浩瀚于堆外 2G,且 JVM 参数不可治愈,是以要想行使好堆内富有的内存去作念缓存,非 HeapByteBuffer 莫属了。

可能有一些读者并没策划注赛题,我这里简化一下绪论,不错径直线路为:有一块 2G 的 HeapByteBuffer 用于文献 IO,咱们该怎么行使。

HeapByteBuffer 的复制问题

谎话未几说,径直来看 HeapByteBuffer 的坑在哪儿。

使用代码形貌 HeapByteBuffer 的文献 IO 操作,约略率会写出如下的代码:

public 澳门永利棋牌void readInOneThread() throws Exception {     int bufferSize = 50 * 1024 * 1024;     File file = new File("/essd");     FileChannel fileChannel = new RandomAccessFile(file, "rw").getChannel();     ByteBuffer byteBuffer = ByteBuffer.allocate(bufferSize);     fileChannel.read(byteBuffer); } 

上述的代码,将文献中的数据缓存到了内存中,无论是赛题如故出产场景,这个活动时常王人是多线程的,举例在云原生编程挑战赛的评测下,有 40 个线程进行读写,如果按照线程维度进行缓存,每个线程分到 50M 用于内存缓存当然是莫得问题。

而如果你径直使用上述代码,在评测中可能会径直获得内存溢出策划的格外。其实我在之前堆外内存表示的著述中也提到过这个问题,不外角度有所不同。原因很肤浅,径直来看源码。

皇冠售后服务电话

FileChannel 使用的是 IOUtil 进行读写操作

static int read(FileDescriptor var0, ByteBuffer var1, long var2, NativeDispatcher var4) throws IOException {     if (var1.isReadOnly()) {         throw new IllegalArgumentException("Read-only buffer");     } else if (var1 instanceof DirectBuffer) {         return readIntoNativeBuffer(var0, var1, var2, var4);     } else {         ByteBuffer var5 = Util.getTemporaryDirectBuffer(var1.remaining());         int var7;         try {             int var6 = readIntoNativeBuffer(var0, var5, var2, var4);             var5.flip();             if (var6 > 0) {                 var1.put(var5);             }             var7 = var6;         } finally {             Util.offerFirstTemporaryDirectBuffer(var5);         }         return var7;     } } 

不错发现当使用 HeapByteBuffer 时,会走到底下这个分支

Util.getTemporaryDirectBuffer(var1.remaining()); 

这个 Util 封装了更为底层的一些 IO 逻辑

package sun.nio.ch; public class Util {     private static ThreadLocal<Util.BufferCache> bufferCache;          public static ByteBuffer getTemporaryDirectBuffer(int var0) {         if (isBufferTooLarge(var0)) {             return ByteBuffer.allocateDirect(var0);         } else {             // FOUCS ON THIS LINE             Util.BufferCache var1 = (Util.BufferCache)bufferCache.get();             ByteBuffer var2 = var1.get(var0);             if (var2 != null) {                 return var2;             } else {                 if (!var1.isEmpty()) {                     var2 = var1.removeFirst();                     free(var2);                 }                  return ByteBuffer.allocateDirect(var0);             }         }     } } 

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 的念念路来优化这一历程。代码示举例下:

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

在 Java 中,从磁盘到堆内内存,一定无法不详堆外内存的复制,但咱们不错我方复制,从而使得这个历程愈加直不雅地被咱们我方操控,而不是被 FileChannel 的里面逻辑摆布。

皇冠客服飞机:@seo3687

这里也需要提防

博彩平台游戏活动

单次 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 并复制的决策。

金融投资网站以其多年博彩行业经验博彩攻略技巧分享,广大博彩爱好者提供全面博彩知识优质博彩服务博彩游戏,您博彩游戏中尽情享受博彩乐趣。葡京娱乐体育赛事彩票

 



上一篇:没有了
下一篇:排列三炸金花博彩网站信誉_天下上最令东谈主不成念念议的桥,不使用钢筋和水泥,而且数目还好多

Powered by 欧博官网网站 @2013-2022 RSS地图

皇冠体育导航皇冠体育皇冠现金网皇冠客服新2网址