Обновление с Java VM 5 до 6 дало действительно большой прирост потребления памяти - PullRequest
4 голосов
/ 26 ноября 2008

Я работаю с 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, и я не могу легко изменить его.

Спасибо

Ответы [ 9 ]

4 голосов
/ 26 ноября 2008

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

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

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

3 голосов
/ 26 ноября 2008

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

java -version

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

1 голос
/ 26 ноября 2008

Использование только команд top / ps для измерения

Нельзя измерить потребление памяти JVM с помощью top или ps.

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

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

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

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

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

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

0 голосов
/ 28 ноября 2008

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

0 голосов
/ 28 ноября 2008

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

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

0 голосов
/ 27 ноября 2008

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

0 голосов
/ 27 ноября 2008

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

Ошибка 6536111

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

0 голосов
/ 26 ноября 2008

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

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

JVM 6:

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

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

JVM 5:

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

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

0 голосов
/ 26 ноября 2008

звучит так, как будто новая JVM торгует памятью для скорости (т. Е. Для кэширования или нет)?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...