这两种类型的ByteBuffer相信大家都知道,但是两者的区别在什么地方呢?在不同的环境下采用哪种类型的ByteBuffer会更有效率呢?
先解释一下两者的区别:
Non-direct ByteBuffer内存是分配在堆上的,直接由Java虚拟机负责垃圾收集,你可以把它想象成一个字节数组的包装类,如下伪码所示:
HeapByteBuffer extends ByteBuffer {
byte[] content;
int position, limit, capacity;
......
}
而Direct ByteBuffer是通过JNI在Java虚拟机外的内存中分配了一块(所以即使在运行时通过-Xmx指定了Java虚拟机的最大堆内存,还是可能
实例化超出该大小的Direct ByteBuffer),该内存块并不直接由Java虚拟机负责垃圾收集,但是在Direct ByteBuffer包装类被回收时,会通过Java Reference机制来释放该内存块。如下伪码所示:
DirectByteBuffer extends ByteBuffer {
long address;
int position, limit, capacity;
protected void finalize() throws Throwable{
//
释放内存块,
该段代码仅仅用于演示,真正的Direct ByteBuffer并不是通过finalize来释放的
releaseAddress();
......
}
......
}
我相信大部分朋友们对上面的区别都应该很了解,那么还有什么其他的区别呢?嘿嘿,让我们稍微深入一点,翻到
sun.nio.ch.IOUtil.java,绝大部分Channel类都是通过这个工具类和外界进行通讯的,如
FileChannel/SocketChannel等等。我简单的用伪码把write方法给表达出来(read方法也差不多,就不多做说明了)
int write(ByteBuffer src, ......) {
if (src instanceof DirectBuffer)
return writeFromNativeBuffer(...);
ByteBuffer direct = getTemporaryDirectBuffer(src);
writeFromNativeBuffer(direct,......);
updatePosition(src);
releaseTemporaryDirectBuffer(direct);
}
是的,在发送和接收前会把Non-direct ByteBuffer转换为Direct
ByteBuffer,然后再进行相关的操作,最后更新原始ByteBuffer的position。这意味着什么?假设我们要从网络中读入一段数据,再
把这段数据发送出去的话,采用Non-direct ByteBuffer的流程是这样的:
网络 --> 临时的Direct ByteBuffer --> 应用 Non-direct ByteBuffer --> 临时的Direct ByteBuffer --> 网络
而采用Direct ByteBuffer的流程是这样的:
网络 --> 应用 Direct ByteBuffer --> 网络
可以看到,除开构造和析构临时Direct ByteBuffer的时间外,起码还能节约两次内存拷贝的时间。那么是否在任何情况下都采用Direct Buffer呢?
不是。对于大部分应用而言,两次内存拷贝的时间几乎可以忽略不计,而构造和析构Direct
Buffer的时间却相对较长。在JVM的实现当中,某些方法会缓存一部分临时Direct ByteBuffer,意味着如果采用Direct
ByteBuffer仅仅能节约掉两次内存拷贝的时间,而无法节约构造和析构的时间。就用Sun的实现来说,write(ByteBuffer)和
read(ByteBuffer)方法都会缓存临时Direct
ByteBuffer,而write(ByteBuffer[])和read(ByteBuffer[])每次都生成新的临时Direct
ByteBuffer。
根据这些区别,我会提出如下的建议:
-
如果你做中小规模的应用(在这里,应用大小是按照使用ByteBuffer的次数和规模来做划分的),而且并不在乎这该死的细节问题,请选择Non-direct ByteBuffer
-
如果采用Direct ByteBuffer后性能并没有出现你所期待的变化,请选择Non-direct ByteBuffer
-
如果没有Direct ByteBuffer Pool,尽量不要使用Direct ByteBuffer
-
除非你确定该ByteBuffer会长时间存在,并且和外界有频繁交互,可采用Direct ByteBuffer
-
如果采用Non-direct
ByteBuffer,那么采用非聚集(gather)的write/read(ByteBuffer)效果反而可能超出聚集的write
/read(ByteBuffer[]),因为聚集的write/read的临时Direct ByteBuffer是非缓存的
基本上,采用Non-direct
ByteBuffer总是对的!因为内存拷贝需要的开销对大部分应用而言都可以忽略不计。不过我做的是大规模的网络并发框架,因此对这些细节问题还是有必
要有深入认识的,并且根据这些细节来调节自己的Buffer继承体系(再次抱怨,ByteBuffer无法扩展实在是一个非常非常非常费解的设计)
注:前面提到的“即使在运行时通过-Xmx指定了Java虚拟机的最大堆内存,还是可能
实
例化超出该大小的Direct
ByteBuffer”中的可能是指可以通过-XX:MaxDirectMemorySize=<size>来指定Direct
ByteBuffer实例最多可以使用的内存总数。如指定-XX:MaxDirectMemorySize=1024,则系统中所有存活的Direct
ByteBuffer总内存数不能超过1024字节。
分享到:
相关推荐
VMware-Horizon-Agent-Direct-Connection-x86_64-7.6.0-9539447
VMware-viewagent-direct-connection-x86_64-6.1.0-2509221
VMware-Horizon-Agent-Direct-Connection-x86-7.6.0-9539447
2010-Direct-Detection LADAR Systems2010-Direct-Detection LADAR Systems2010-Direct-Detection LADAR Systems2010-Direct-Detection LADAR Systems2010-Direct-Detection LADAR Systems2010-Direct-Detection ...
Direct3D是微软开发的一种图形应用程序接口(API),主要用于创建高性能的三维图形,尤其是在游戏开发和专业图形渲染领域。这个“Direct3D起步-教程”是为初学者设计的,旨在帮助他们理解Direct3D的基本概念和技术,...
vlc-direct-pro-free-4-1-es-en-android android上的手机遥控播放器播放的软件。
directx修复工具,query-shared-vram-by-direct-x-master.zip
Direct-load-apk是一个非常强大的插件框架,通过使用它,你可以实现不可思议的功能-----从一个基本的apk直接加载! 优势: direct-load-apk 可以加载一个apk的所有资源。 支持在插件 Activity之间跳转。 不喜欢...
从网上收集的DirectUI资料,可以轻松实现类似360,QQ的界面。其中有几个是收费版的demo,有几个是开发源码的demo。有源码的几个工程中的控件都不是标准的Windows控件,当然没有收费版的方便。如果需求不是很大,可以...
direct-links-out, 从链接中删除所有"You are leaving our site" 内容 直接链接将所有这些"你离开我们的网站"和其他重定向内容从链接中删除的Userscript 。更好的匿名性快速浏览纯 JavaScript安装( OpenUserJS ): ...
《MetaTrader 5中的i-KlPrice_Vol_Direct_HTF脚本详解》 MetaTrader 5(MT5)是一款广泛应用于外汇、期货和股票市场的交易平台,它为交易者提供了丰富的技术分析工具和自动化交易功能。本文将深入探讨标题为“i-...
图像拼接领域论文Direct_Photometric_Alignment_by_Mesh_Deformation复现代码,python实现,image stitching。通过网格变形直接光学配准。文章地址:https://blog.csdn.net/qq_36584673/article/details/122300266
该程序是我编写的一简单的三维程序,程序运行以后,会显示一个四棱锥,按任意键会旋转,按鼠标右键会倒退,在VC6下编译通过,编译时要注意该程序为一个Win32窗口程序并且有Direct3D支持。
git clone https://github.com/koide3/direct_visual_lidar_calibration.git --recursive 构建好模型的完整代码
遗传算法与直接搜索工具箱(Genetic Algorithm and Direct Search Toolbox)是MATLAB环境下的一款高级工具包,主要用于解决优化问题中的复杂挑战。此工具箱结合了遗传算法和直接搜索方法,为用户提供了强大的优化...
Performance analysis of an all-digital BPSK direct-sequence spread-spectrum IF receiver architecture1993.pdf
在Linux上设置Wi-Fi Direct连接 Linux上的WiFi Direct 因此,我尝试使用Wifi-Direct连接两个设备。 一个是装有Linux的PC,另一个是Android智能手机。 我希望将Linux作为GO,将Android作为客户端。 为了建立Wifi...
该程序用于单力臂机械手直接自适应模糊控制,用于研究机器人的控制
【Torus-Swift-Direct-SDK-Demo应用程序】是一个基于Swift编程语言的示例应用,它展示了如何使用Torus Swift Direct SDK进行集成和开发。这个SDK主要用于与Torus存储平台进行直接交互,提供高效、安全的数据存取功能...
direct sequence spread spectrum matlab program to achieve the spreading of original data