Возможная утечка памяти при использовании JOGL с использованием VBO - PullRequest
2 голосов
/ 12 августа 2011

В настоящее время мы разрабатываем приложение, которое визуализирует огромные векторные поля (> 250'000) на сфере / плоскости в 4D.Чтобы ускорить процесс, мы используем VBO для вершин, нормалей и цветов.Для подготовки данных перед отправкой в ​​графический процессор мы используем буферы (FloatBuffer, ByteBuffer и т. Д.).

Некоторые данные для цилиндров: каждый цилиндр использует 16 * 9 + 16 * 3 = 192 числа с плавающей запятой -> 192 * 4 байта = 768 байтов.

После отправки вершин мы выполняемследующая очистка:

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

vertexBufferShell = null;
indexBufferShell = null;

Мы наблюдали за этим с помощью JConsole, и мы обнаружили, что GarbageCollector не работает "правильно".Даже если мы выключим счетчик цилиндров, память не освободится.В инструменте мониторинга JConsole есть кнопка для запуска ГХ, и если мы делаем это вручную, это освобождает память (если мы загрузили огромное количество цилиндров и сильно его уменьшили, иногда ГХ очищает более 600 МБ).

Вот изображение JConsole: JConsole Output, Memory does get cleanup after pushing the Perform GC button

Теперь вопрос заключается в том, как мы можем самостоятельно очистить этот буфер в коде?Вызов метода clear и установка ссылки на null недостаточно.Мы также пытались вызвать System.gc () , но безрезультатно.У вас есть идеи?

Ответы [ 4 ]

3 голосов
/ 12 августа 2011

Существует множество причин, по которым использование памяти может увеличиться. Я бы сказал, что это не утечка памяти, если память не увеличивается каждый раз, когда вы выполняете эту операцию. Если это происходит только в первый раз, возможно, для загрузки этой библиотеке требуется некоторое количество памяти.

Я предлагаю вам сделать дамп кучи или хотя бы jmap -histo:live до и после, чтобы увидеть, где происходит увеличение памяти.

Если вы используете профилировщик памяти, такой как VisualVM или YourKit, он покажет вам, где и почему сохраняется память.

1 голос
/ 13 августа 2011

JVM не будет освобождать какие-либо объекты, пока это не будет необходимо (например, достигнут Xmx). Это одна из основных концепций всех GC, которые вы можете найти в текущей JVM. Все они оптимизированы для пропускной способности, даже параллельной. Я не вижу ничего необычного на графике ГХ.

Было бы утечкой, если использованная куча после полного GC будет постоянно расти со временем - если нет -> все хорошо.

короче: foo = null; не будет освобождать объект только ссылку. GC может освободить память, когда захочет.

также: buffer.clear () не очищает буфер, он устанавливает pos = 0 и limit = емкость - вот и все. Пожалуйста, обратитесь к javadoc для получения дополнительной информации.

VisualVM + 1

веселись :) 1013 *

(offtopic: если буферы большие и статические, вы должны разместить их в permgen. Buffers.newDirectFloatBuffer () будет одним из тех служебных методов в последнем gluegen-rt)

1 голос
/ 12 августа 2011

Это на самом деле не утечка памяти, если gc может ее почистить. Это может быть пустой тратой памяти, но ваше приложение, похоже, настроено так, чтобы оно могло использовать более 800 МБ кучи. Это компромисс между производительностью сборки мусора и использованием памяти. Вы также можете попробовать запустить приложение с меньшим размером кучи.

1 голос
/ 12 августа 2011

Возможно, не произошла утечка памяти, но объекты идут в Ternured (область, в которую попадают объекты, прошедшие живым в минорном gc).

Этим большим шагом, который вы видите, может быть Young Eden, который заполнен, и после того, как незначительный ГК перемещает живые объекты в Ternure.

Вы также можете попытаться настроить сборщик мусора и память.

у вас может быть много живых объектов средней длины, которые постоянно передаются на Ternured, освобождая их в полном объеме. Если вы измеряете их хорошо, эти объекты становятся незначительными.

Для этого существует множество аргументов jvm.

Хорошее место, чтобы посмотреть на это здесь .

Этот подходит для вас:

-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]

Привет.

...