使用VBO使用JOGL可能导致内存泄漏

时间:2011-08-12 09:59:32

标签: java opengl buffer jogl vbo

我们目前正在开发一种应用程序,它可以在4D中在球体/平面上显示巨大的矢量场(> 250'000)。为了加快这个过程,我们使用VBO作为顶点,法线和颜色。为了在发送到GPU之前准备数据,我们使用Buffers(FloatBuffer,ByteBuffer等)。

气缸的一些数据: 每个气缸使用16 * 9 + 16 * 3 = 192个浮子 - > 192 * 4字节= 768字节。

在发送顶点后,我们正在进行以下清理:

// clear all buffers
vertexBufferShell.clear();
indexBufferShell.clear();

vertexBufferShell = null;
indexBufferShell = null;

我们已经使用JConsole监视它,我们发现GarbageCollector没有“正确”运行。即使我们切换气缸数,内存也不会被释放。在JConsole监视工具中有一个用于运行GC的按钮,如果我们手动执行该操作,则会释放内存(如果我们已经加载了大量的柱面并且减少了很多,有时超过600mb会被GC清理)。

这里是JConsole的图片: JConsole Output, Memory does get cleanup after pushing the Perform GC button

现在的问题是我们如何在代码中自行清理这个缓冲区?调用clear方法并将引用设置为null是不够的。我们还尝试调用 System.gc(),但没有效果。你有什么想法吗?

4 个答案:

答案 0 :(得分:3)

内存使用量增加有多种原因。我会说它不是内存泄漏,除非每次执行此操作时内存都会增加。如果它仅在第一次出现时,可能是该库需要一些内存来加载。

我建议您在之前和之后进行堆转储或至少jmap -histo:live以查看内存增加的位置。

如果您使用像VisualVM或YourKit这样的内存分析器,它将显示内存保留的位置和原因。

答案 1 :(得分:1)

可能没有内存泄漏,但是对象转到Ternured(在次要gc中传递活动的对象所在的区域)。

您看到的这一重要步骤可能是Young Eden已满并且在次要gc将活动对象移至Ternure之后。

您还可以尝试调整垃圾收集器和内存。

你可能有很多中等长度的活动对象,它们不断传递给Ternured以完全gc释放它们。如果你很好地标注它们那些对象会变成次要的gc。

有很多jvm参数可以做到这一点。

值得关注的一个好地方是here

这个适合你:

-XX:NewSize=2.125m 
Default size of new generation (in bytes) 
[5.0 and newer: 64 bit VMs are scaled 30% larger; x86: 1m; x86, 5.0 and older: 640k]

问候。

答案 2 :(得分:1)

如果gc能够清理它,它实际上不是内存泄漏。这可能是浪费内存,但您的应用程序似乎配置为允许它使用超过800MB的堆。这是垃圾收集性能和内存使用之间的权衡。您还可以尝试使用较小的堆大小运行应用程序。

答案 3 :(得分:1)

JVM不会释放任何对象,直到它必须(例如,到达Xmx)。这是您可以在当前JVM中找到的所有GC背后的主要概念之一。它们都针对吞吐量进行了优化,即使是并发的吞吐量。我在GC图表上看不到任何异常。

如果完整GC之后使用的堆会随着时间的推移不断增长 - 如果没有 - 那么这将是一个泄漏 - >好的。

简而言之:foo = null;不会仅释放对象的引用。 GC可以随时释放内存。

也: buffer.clear()不清除缓冲区,它设置pos = 0和limit = capacity - 这就是全部。有关详细信息,请参阅javadoc。

VisualVM +1

玩得开心:)

(offtopic:如果缓冲区很大而且是静态的,你应该在permgen中分配它们.Buffers.newDirectFloatBuffer()将是最新的gluegen-rt中的那些实用方法之一)