Потребление памяти Java, "top" и HP-Ux

Мы поставляем Java-приложения, которые работают на Linux, AIX и HP-Ux (PA-RISC). Похоже, мы изо всех сил пытаемся получить приемлемый уровень производительности в HP-Ux от приложений, которые прекрасно работают в двух других средах. Это относится как к времени выполнения, так и к потреблению памяти.

Хотя мне еще предстоит найти определенную статью о "почему", я считаю, что измерение потребления памяти с использованием "top" - это грубый подход, поскольку такие вещи, как общий код, дают неверные результаты. Тем не менее, это почти все, что нам нужно сделать на сайте клиента, где потребление памяти в HP-Ux стало проблемой. Это стало проблемой только тогда, когда мы перешли с Java 1.4 на Java 1.5 (на HP-Ux 11.23 PA-RISC). Под "проблемой" я подразумеваю, что машина перестала создавать новые процессы, потому что мы исчерпали все 16 ГБ физической памяти.

Измеряя "до" и "после" общей "свободной памяти", мы пытаемся измерить, сколько было использовано приложением Java. Я написал быстрое приложение, которое хранит 10000 случайных 64-битных строк в ArrayList, и попробовал этот подход для измерения потребления в Linux и HP-Ux в Java 1.4 и Java 1.5.

Результаты, достижения:

HP Java 1.4 ~ 60MB

HP Java 1,5 ~150 МБ

Linux Java 1.4 ~ 24MB

Linux Java 1.5 ~ 16MB

Кто-нибудь может объяснить, почему эти результаты могут возникнуть? Это какая-то особенность способа, которым "верх" измеряет свободную память? Действительно ли Java 1.5 на HP потребляет в 2,5 раза больше памяти, чем Java 1.4?

Благодарю.

4 ответа

JVM могут просто иметь разные параметры по умолчанию. Куча будет расти до размера, который вы настроили, чтобы позволить ей. По умолчанию на виртуальной машине Sun установлен определенный процент ОЗУ в машине - то есть, по умолчанию Java будет использовать больше памяти, если вы используете машину с большим объемом памяти.

Я был бы очень удивлен, если бы у виртуальной машины HP-UX не было много настроек для такого рода вещей HP. Я бы посоветовал вам поэкспериментировать с параметрами обоих - выяснить, какой наименьший максимальный размер кучи вы можете использовать без ущерба для производительности или пропускной способности.

У меня сейчас нет коробки HP для проверки моей гипотезы. Однако на вашем месте я бы использовал профилировщик, такой как JConsole(поставляется с JDK) ИЛИ yourkit, чтобы измерить происходящее.

Однако, похоже, что вы начали измерения после того, как увидели что-то неладное; Так что я НЕ дисконтирую, что это происходит - просто указываю вам на то, что я сделал бы в той же ситуации.

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

Вы запускаете несколько виртуальных машин? Вы читаете большие наборы данных в память и не удаляете их достаточно быстро? и т. д. и т. д.

Во-первых, неясно, что вы измерили тестом "10000 случайных 64-битных строк". Вы должны запустить приложение, измерить его загрузочный объем памяти, а затем запустить тест. Вполне возможно, что Java 1.5 получает больше кучи сразу после запуска (например, из-за настроек менеджера кучи).

Во-вторых, мы запускаем приложения Java под 1.4, 1.5 и 1.6 под HP-UX, и они не предъявляют особых требований к памяти. Хотя у нас есть Itanium.

В-третьих, почему вы используете топ? Почему бы просто не напечатать Runtime.getRuntime(). TotalMemory()?

В-четвертых, добавляя значения в ArrayList, вы создаете фрагментацию памяти. ArrayList должен удваивать свое внутреннее хранилище время от времени. В зависимости от настроек GC и реализации ArrayList.ensureCapacity() объем не собранной памяти может существенно различаться между 1,4 и 1,5.

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

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