ByteBuffer.allocate()和ByteBuffer.allocateDirect()

| 问题是“ 0”还是“ 1”。 几年以来,我一直坚持认为,由于ѭ2是操作系统级别的直接内存映射,因此它的执行get / put调用的速度比ѭ3更快。到目前为止,我从来没有真正对找到有关该情况的确切细节感兴趣。我想知道ѭ4的两种类型中哪种更快,在什么条件下。     
已邀请:
罗恩·希切斯(Ron Hitches)在他的著作《 Java NIO》中似乎提供了我认为可以很好地回答您的问题的答案:   操作系统执行I / O   对存储区的操作。这些   内存区域,据操作   系统而言,是连续的   字节序列。不足为奇   那么只有字节缓冲区是   有资格参与I / O   操作。还记得   操作系统将直接访问   进程的地址空间,在   这种情况下的JVM进程,要转移   数据。这意味着内存区域   I / O操作的目标必须   是连续的字节序列。在   JVM,字节数组可能不是   连续存储在内存中,或者   垃圾收集器可以随时移动它   时间。数组是Java中的对象,并且   数据存储在其中的方式   对象可能与一个JVM不同   实施到另一个。      因此,   引入了直接缓冲区。直接   缓冲区用于交互   带有通道和本机I / O例程。   他们尽力存储   存储区中的字节元素   频道可用于直接或原始   通过使用本机代码来访问   操作系统耗尽或填充   直接存储区域。      直接字节缓冲区通常是   I / O操作的最佳选择。通过   设计,他们最支持   高效的I / O机制可用于   JVM。非直接字节缓冲区可以是   传递给渠道,但这样做可能   会产生性能损失。它的   对于非直接人通常是不可能的   缓冲区成为本机目标   I / O操作。如果您通过非直接   ByteBuffer对象用于通道   写,通道可以隐式地做   每次通话以下内容:         创建一个临时直接ByteBuffer   宾语。   复制非直接内容   缓冲区到临时缓冲区。   执行底层I / O操作   使用临时缓冲区。   临时缓冲区对象熄灭   范围,最终是垃圾   集。         这可能会导致缓冲   在每个I / O上复制和搅动对象,   正是这些东西   我们想避免。但是,取决于   在实施上,事情可能不会   这么糟糕。运行时可能   缓存和重用直接缓冲区或   执行其他巧妙的技巧来提升   吞吐量。如果您只是在创建   一次性使用的缓冲区   差别不大。在   另一方面,如果您将使用   反复缓冲   高性能场景,   更好地分配直接缓冲区   并重用它们。      直接缓冲区最适合I / O,   但它们可能更昂贵   比非直接字节缓冲区创建。   直接缓冲区使用的内存是   通过调用来分配   本机的,特定于操作系统的   代码,绕过标准的JVM堆。   直接设置和拆卸   缓冲区可能会更多   比堆驻留缓冲区昂贵,   取决于主机操作系统   和JVM实现。的   直接缓冲区的内存存储区   不受垃圾收集   因为它们超出了标准   JVM堆。      使用的性能折衷   直接和非直接缓冲区可以   JVM,操作系统,   和代码设计。通过分配内存   在堆外面,您可能会使您的   施加于   JVM不知道。什么时候   引入其他运动部件   玩,确保自己达到目标   预期的效果。我推荐   旧软件格言:首先做到   工作,然后使其快速。不用担心   太多关于预先优化的内容;   首先专注于正确性。的   JVM实现可能能够   执行缓冲区缓存或其他   优化将为您提供   您无需太多的性能   您不必要的努力。     
没有理由期望直接缓冲区可以更快地进入jvm。当您将它们传递给本机代码时(例如,各种渠道背后的代码),它们的优势就会显现出来。     
  因为DirectByteBuffers是直接的   操作系统级别的内存映射 他们不是。它们只是正常的应用程序进程内存,而在Java GC期间不会进行重定位,从而大大简化了JNI层中的内容。您描述的内容适用于
MappedByteBuffer
。   使用get / put调用可以更快地执行 结论并非来自前提。前提是假的;结论也是错误的。一旦进入JNI层,它们将更快,并且如果您从同一“ 2”进行读写,它们将更快,因为数据根本不需要越过JNI边界。     
最好自己做测量。快速的答案似乎是,从
allocateDirect()
缓冲区发送数据所花费的时间比
allocate()
变体(经测试将文件复制到/ dev / null)要少25%到75%,具体取决于大小,但是分配本身可能会明显变慢(甚至是100倍)。 资料来源: 为什么ByteBuffer.allocate()和ByteBuffer.allocateDirect()之间的奇异性能曲线差异 ByteBuffer.allocateDirect太慢了 何时使用数组,缓冲区或直接缓冲区     

要回复问题请先登录注册