DirectByteBuffer更快吗?

对着背影说爱祢 提交于 2019-12-02 14:38:18

ByteBuffer.allocateDirect  vs  ByteBuffer.allocate

操作系统的IO机制

    操作系统在内存区域上执行IO操作,这些内存区域是连续的字节。毫无疑问只有字节缓冲区才有资格参与IO操作的。同样操作系统会直接访问进程空间,包括JVM进程,传输数据。JVM内部,字节数组可能不是连续的,或者GC任意时刻会移动这些字节。Java内部数组是对象,对象内部数据存储的方式,是跟JVM实现相关的。

引入Direct Buffer

    出于这个原因,引入了direct buffer。direct buffer就是为了和channel和本地IO例程交互。direct buffer的实现会尽量让channel直接使用,本地操作系统代码能够直接读写。

利弊

    直接缓冲区通常是IO操作的最佳选择,是JVM能够使用的最高效的IO机制。non-direct缓冲区可以传递给channel,但通常会带来性能损耗。通常non-direct缓冲区不是本地IO操作的直接目标。如果让channel写non-direct ByteBuffer,channel会隐含的执行下列步骤:

    创建临时的direct ByteBuffer

    复制non-direct buffer中的内容到临时buffer

    使用临时buffer执行IO操作

    临时buffer不被引用,最终被垃圾收集

    这会潜在的导致每次IO操作中的缓冲区复制和Object Churn,这正是我们想避免的。然而取决于实现,事情可能并不会这么坏。JVM运行时可能会缓存和重用direct缓冲区,或着其它技巧来提高吞吐量。如果创建只使用一次的缓冲区,这两者的区别并不明显。如果在高性能的场景中频繁使用buffer,那么最好使用direct缓冲区。

    direct缓冲区最适合IO,但是可能创建更加耗时。direct缓冲区使用的内存,绕过了JVM堆,通过本地代码调用分配。创建和销毁都要比驻留在JVM堆里的缓冲区更加耗时(依赖于操作系统和JVM实现)。direct缓冲区使用的内存不受垃圾收集的控制,因为它们在JVM堆的外部。

总结

    使用direct还是non-direct的性能考虑依赖于JVM,操作系统,和应用代码。在JVM堆外分配内存,把应用受制于JVM不能监管的一些额外机制。让额外的一些机制起作用,一定要保证你获得了想要的效果。我推荐古老的设计哲学,“首先让他工作,然后让他更快”。不要提前担心优化,首先关注应用的正确。JVM实现可能会执行一些优化,给你想要的性能,这样就免除了开发者的负担。

原文 From:http://stackoverflow.com/questions/5670862/bytebuffer-allocate-vs-bytebuffer-allocatedirect

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!