BufferUtils 和 MemoryUtil 有什么区别? (LWJGL)
What's the difference between BufferUtils and MemoryUtil? (LWJGL)
我总是使用 MemoryUtil
来存储浮动缓冲区,但人们似乎使用 BufferUtils
来存储它:
private IntBuffer convertToIntBuffer(int[] data) {
IntBuffer buffer = BufferUtils.createIntBuffer(data.length);
return buffer.put(data).flip();
}
private FloatBuffer convertToFloatBuffer(float[] data) {
FloatBuffer buffer = MemoryUtil.memAllocFloat(data.length);
return buffer.put(data).flip();
}
LWJGL 3 的 org.lwjgl.BufferUtils
class 只是 Java 的 java.nio.ByteBuffer.allocateDirect()
方法的一个小外观,允许您使用 JVM 的内存分配器分配堆外内存内存和 return NIO ByteBuffer
(或其类型化视图),包括确保 ByteOrder 是 nativeOrder()
.
ByteBuffer.allocateDirect()
分配的 NIO 缓冲区由 JRE 内部管理,一旦无法访问,本机内存将作为垃圾收集周期的一部分隐式释放。
使用这种方法分配堆外内存有很多缺点,例如(引自“Memory management in LWJGL 3”):
-引用开始-
它很慢,比原始 malloc() 调用慢得多。在一个已经很慢的函数之上有很多开销。
它在争用下扩展性很差。
任意限制分配的内存量(-XX:MaxDirectMemorySize)。
与 Java 数组一样,分配的内存总是清零。这不一定是坏事,但有选择会更好。
无法按需解除分配的内存(没有 JDK 特定的反射 hack)。相反,使用引用队列通常需要两个 GC 周期来释放本机内存。这在压力下经常会导致 OOM 错误。
-引用结束-
LWJGL 3 的 org.lwjgl.system.MemoryUtil
class 另一方面允许您使用其他 native/off-heap 内存分配器而不是 JVM 的 ByteBuffer 分配器来分配堆外本机内存,包括选项只是给你原始虚拟内存地址作为 long
,避免 NIO Buffer
实例。
LWJGL 支持 C 标准库 (malloc) 的系统分配器以及当前 jemalloc and rpmalloc。所有这些都提供了比 Java 的 ByteBuffer.allocateDirect() 快得多的替代方法,减轻了上述缺点。
因为本机内存不再由 JVM 管理,您必须自己释放内存,为此有org.lwjgl.system.MemoryUtil.memFree()
方法。
在继续之前,您应该完整阅读提到的 LWJGL 博客 post,因为有更多选项,例如 org.lwjgl.system.MemoryStack
,用于在特定情况下分配本机堆外内存(例如短暂的内存),甚至比上面提到的所有其他替代方案更快。
我总是使用 MemoryUtil
来存储浮动缓冲区,但人们似乎使用 BufferUtils
来存储它:
private IntBuffer convertToIntBuffer(int[] data) {
IntBuffer buffer = BufferUtils.createIntBuffer(data.length);
return buffer.put(data).flip();
}
private FloatBuffer convertToFloatBuffer(float[] data) {
FloatBuffer buffer = MemoryUtil.memAllocFloat(data.length);
return buffer.put(data).flip();
}
LWJGL 3 的 org.lwjgl.BufferUtils
class 只是 Java 的 java.nio.ByteBuffer.allocateDirect()
方法的一个小外观,允许您使用 JVM 的内存分配器分配堆外内存内存和 return NIO ByteBuffer
(或其类型化视图),包括确保 ByteOrder 是 nativeOrder()
.
ByteBuffer.allocateDirect()
分配的 NIO 缓冲区由 JRE 内部管理,一旦无法访问,本机内存将作为垃圾收集周期的一部分隐式释放。
使用这种方法分配堆外内存有很多缺点,例如(引自“Memory management in LWJGL 3”):
-引用开始-
它很慢,比原始 malloc() 调用慢得多。在一个已经很慢的函数之上有很多开销。
它在争用下扩展性很差。
任意限制分配的内存量(-XX:MaxDirectMemorySize)。
与 Java 数组一样,分配的内存总是清零。这不一定是坏事,但有选择会更好。
无法按需解除分配的内存(没有 JDK 特定的反射 hack)。相反,使用引用队列通常需要两个 GC 周期来释放本机内存。这在压力下经常会导致 OOM 错误。
-引用结束-
LWJGL 3 的 org.lwjgl.system.MemoryUtil
class 另一方面允许您使用其他 native/off-heap 内存分配器而不是 JVM 的 ByteBuffer 分配器来分配堆外本机内存,包括选项只是给你原始虚拟内存地址作为 long
,避免 NIO Buffer
实例。
LWJGL 支持 C 标准库 (malloc) 的系统分配器以及当前 jemalloc and rpmalloc。所有这些都提供了比 Java 的 ByteBuffer.allocateDirect() 快得多的替代方法,减轻了上述缺点。
因为本机内存不再由 JVM 管理,您必须自己释放内存,为此有org.lwjgl.system.MemoryUtil.memFree()
方法。
在继续之前,您应该完整阅读提到的 LWJGL 博客 post,因为有更多选项,例如 org.lwjgl.system.MemoryStack
,用于在特定情况下分配本机堆外内存(例如短暂的内存),甚至比上面提到的所有其他替代方案更快。