Обновление с Java VM 5 до 6 дало действительно большое увеличение потребления памяти

Я работаю с Java-приложением, запускаемым из командной строки. Он имеет дело с файлами XML, особенно с базой данных dblp.xml, размер которой превышает 400 МБ.

Я использовал JVM 5, и моему приложению требовалось около 600-700 МБ памяти для обработки dblp.xml. После обновления до JVM 6 ему стало требоваться более 1 ГБ памяти (чего у меня нет), хотя он работает немного быстрее.

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

Я не устанавливал никаких специальных параметров, просто -Xmx800M или -Xmx1000M. Работает с Ubuntu Hardy Heron на двухъядерном процессоре 1,7 ГГц, с 1,5 ГБ памяти Использование только команд top / ps для измерения

У кого-нибудь есть идея, почему это происходит? Я действительно хотел использовать JVM 6, потому что на моем рабочем сервере используется JVM, и я не могу легко ее изменить.

Спасибо

Как вы измеряете потребление памяти и какая у вас операционная система?

Dan Dyer 26.11.2008 04:44

Ubuntu Hardy Heron Я использую только команды top / ps, но разница слишком велика. С Java 5 приложение завершает обработку, с Java 6 - нет. Спасибо за ответ.

Felipe Hummel 26.11.2008 06:45

Дополнительная информация: Я запускаю его на двухъядерном процессоре 1,7 ГГц с 1,5 ГБ памяти.

Felipe Hummel 26.11.2008 06:50
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
4
3
2 494
9

Ответы 9

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

Угадывать причину проблем с производительностью - плохая идея, потому что вы почти всегда ошибаетесь в своих предположениях и тратите время на оптимизацию не той части системы. Как только у вас появятся объективные данные, вы сможете предложить оптимизацию, уменьшающую потребление памяти.

Если верно, что более новая JVM меняет память на скорость (путем кэширования), то, вероятно, есть аргумент jvm, который вы можете использовать, чтобы остановить это поведение. Лучше всего ознакомиться с примечаниями к выпуску Java 6 и посмотреть, упоминается ли какая-либо такая функция.

звучит так, как будто новая JVM меняет память на скорость (например, кеширование или что-то еще)?

Может быть, вы использовали 32-битную JVM 1.5 и 64-битную 1.6 JVM? Вы можете узнать, 32-битная это или 64-битная JVM с

java -version

64-битной JVM требуется примерно на 30% больше памяти по сравнению с 32-битной JVM, поскольку вам нужно 8 байтов для каждой ссылки вместо 4 байтов.

Ничто в команде "java -version" не говорит мне, что это 64-битная версия (ни 32-битная), есть ли более конкретный способ проверить, является ли это 64-битной версией (хотя я думаю, что это не так). Но я получил и то, и другое от "apt-get".

Я просто попытался запустить приложение с аргументом -d32 (чтобы заставить 32 бита, модель данных), похоже, что он использует немного меньше памяти, но он по-прежнему использует намного больше, чем с jvm 5

JVM 6:

/ usr / lib / jvm / java-6-солнце / jre / bin / java -версия версия java "1.6.0_07" Среда выполнения Java (TM) SE (сборка 1.6.0_07-b06) Клиентская виртуальная машина Java HotSpot (TM) (сборка 10.0-b23, смешанный режим, совместное использование)

(на моем сервере) java -version версия java "1.6.0" Среда выполнения Java (TM) SE (сборка 1.6.0-b105) Клиентская виртуальная машина Java HotSpot (TM) (сборка 1.6.0-b105, смешанный режим)

JVM 5:

java -version версия java "1.5.0_16" Java (TM) 2 Runtime Environment, Standard Edition (сборка 1.5.0_16-b02) Клиентская виртуальная машина Java HotSpot (TM) (сборка 1.5.0_16-b02, смешанный режим, совместное использование)

Спасибо за ответы

если в выводе «java -version» нет строки вроде «Java HotSpot (TM) 64-Bit Server VM», у вас 32-битные JVM. Отредактируйте этот ответ и добавьте результат обоих вызовов "java -version".

the.duckman 26.11.2008 19:06

Спасибо за редактирование. Насколько я могу судить, вы используете 32-битные JVM. Возможно, вы захотите сравнить размеры генерации сборщика мусора с jconsole. Может быть, у вас есть ключ к разгадке. Я широко использую как 1.5, так и 1.6 и не могу подтвердить ваши наблюдения своими приложениями, интенсивно использующими память.

the.duckman 26.11.2008 22:42

Using only the top/ps commands to measure

Вы не можете измерить потребление памяти JVM с top или ps.

JVM довольно жадно резервирует память. Иногда это происходит даже без попытки освободить уже зарезервированную память с помощью сборки мусора. (Вы можете попробовать указать параметр -Xms, чтобы изменить это. Прочтите это, чтобы узнать (много) больше.)

top и ps показывают только объем зарезервированной в данный момент памяти, а не память, фактически используемую вашим Java-приложением!

Если вы хотите правильно измерить используемую память, вы должны измерить ее с помощью самой Java. Подход грубой силы будет выглядеть так:

System.gc();
Runtime runtime = Runtime.getRuntime();
long memUsedInBytes = runtime.totalMemory() - runtime.freeMemory();

(Пожалуйста, только для целей отладки и никогда в производственном коде! System.gc() - это зло.)

Но я думаю, вы столкнетесь с OutOfMemoryErrors с -Xmx800M и 1.6, а 1.5 работает нормально. Если это так, этот ответ является лишь второстепенным, потому что тогда у вас действительно есть разница в потреблении памяти.

Я знаю, что top / ps - не лучший способ, но это первый способ увидеть, что что-то идет не так. Ваша догадка верна. Но спасибо за замечание. Я попробую профилировать, чтобы увидеть, что не так. На данный момент, думаю, я просто буду придерживаться JVM 5, пока не найду решение. Спасибо за ответы.

Felipe Hummel 27.11.2008 01:43

Возможно, более простой способ измерения потребления памяти - подключить JConsole к виртуальной машине, затем использовать ее для принудительного создания сборщика мусора, а затем посмотреть на график использования кучи, чтобы узнать потребление памяти.

Leigh 28.11.2008 18:56

Что вы используете для анализа XML-файла? В исходной библиотеке Java 6 была ошибка, которая вызвала такое поведение:

Ошибка 6536111

В комментариях есть обходной путь.

Какой JDK вы используете? Я бы порекомендовал вам попробовать Sun JDK (серверная версия), поскольку JRE (клиентская версия) не так эффективно использует память.

вы можете проверить с помощью jconsole

x86 - 32 бит. Если вы действительно хотите знать, где используется память, получите Анализатор памяти Eclipse

Возможно, ваша предыдущая виртуальная машина использовала клиентский движок (например, «java -client»), в то время как текущая использует серверный движок («java -server»), который использует больше памяти, чтобы иметь гораздо более высокие скорости. Вы можете увидеть это в выводе "java -version". Используемый по умолчанию механизм может быть установлен в jvm.cfg (см. http://forums.sun.com/thread.jspa?threadID=5185368&tstart=1314 для более подробной информации).

Нет. Оба работают под управлением клиента, хотя я пробовал использовать оба сервера, и потребление памяти продолжалось.

Felipe Hummel 28.11.2008 23:01

Другие вопросы по теме