BufferUtils 和 MemoryUtil 有什么区别?(吕文金GL)

Pea*_*ace 5 java memory buffer lwjgl

我总是用来MemoryUtil存储浮动缓冲区,但人们似乎使用BufferUtils它:

private IntBuffer convertToIntBuffer(int[] data) {
    IntBuffer buffer = BufferUtils.createIntBuffer(data.length);        
    return buffer.put(data).flip();
}
Run Code Online (Sandbox Code Playgroud)
private FloatBuffer convertToFloatBuffer(float[] data) {
    FloatBuffer buffer = MemoryUtil.memAllocFloat(data.length);     
    return buffer.put(data).flip();
}
Run Code Online (Sandbox Code Playgroud)

Kai*_*ack 3

LWJGL 3 的org.lwjgl.BufferUtils类只是 Javajava.nio.ByteBuffer.allocateDirect()方法的一个小外观,允许您使用 JVM 的内存分配器来分配堆外内存并返回 NIO ByteBuffer(或其类型化视图),包括确保 ByteOrder 为nativeOrder().

分配的 NIO 缓冲区由ByteBuffer.allocateDirect()JRE 内部管理,并且一旦无法访问本机内存,就会作为垃圾收集周期的一部分隐式释放本机内存。

使用这种方法分配堆外内存有很多缺点,例如(引用自“ LWJGL 3 中的内存管理”):

-引用开始-

  • 它很慢,比原始的 malloc() 调用慢得多。在已经很慢的函数之上会产生大量开销。

  • 在竞争下它的扩展性很差。

  • 它任意限制分配的内存量(-XX:MaxDirectMemorySize)。

  • 与 Java 数组一样,分配的内存始终清零。这不一定是坏事,但有选择会更好。

  • 无法按需释放已分配的内存(没有 JDK 特定的反射 hack)。相反,使用引用队列通常需要两个 GC 周期来释放本机内存。这通常会在压力下导致 OOM 错误。

-引用结束-

org.lwjgl.system.MemoryUtil另一方面,LWJGL 3 的类允许您使用其他本机/堆外内存分配器而不是 JVM 的 ByteBuffer 分配器来分配堆外本机内存,包括只为您提供原始虚拟内存地址作为 的选项long,避免蔚Buffer来实例。

LWJGL 支持 C 标准库的系统分配器 (malloc) 以及当前的jemallocrpmalloc。所有这些都提供了比 Java 的 ByteBuffer.allocateDirect() 更快的替代方案,从而减轻了上述缺点。

由于本机内存不再由 JVM 管理,因此您必须自己释放内存,为此有org.lwjgl.system.MemoryUtil.memFree()方法。

然而,在继续之前,您应该完整阅读提到的 LWJGL 博客文章,因为还有更多选项,例如org.lwjgl.system.MemoryStack用于在特定情况下分配本机堆外内存(例如短期内存),这甚至比上述所有其他替代方案。