Максимальный размер кучи Java, сколько это слишком много

У меня проблемы с приложением JRuby (rails), работающим в tomcat. Время от времени запросы страниц могут возвращаться до минуты (даже несмотря на то, что журналы рельсов обрабатывали запрос в считанные секунды, так что, очевидно, это проблема кота).

Мне интересно, какие настройки являются оптимальными для размера кучи Java. Я знаю, что нет однозначного ответа, но я подумал, что кто-то может прокомментировать мои настройки.

Я нахожусь на небольшом экземпляре EC2, который имеет 1,7 г оперативной памяти. У меня есть следующие JAVA_OPTS:

-Xmx1536m -Xms256m -XX:MaxPermSize=256m -XX:+CMSClassUnloadingEnabled

Моя первая мысль, что Xmx слишком высок. Если у меня только 1,7 ГБ, и я выделил 1,5 ГБ для Java, я чувствую, что получу много страниц. Как правило, мой процесс Java показывает (сверху) 1.1g памяти Res и 2g виртуальной.

Я также где- то читал, что установка Xms и Xmx на один и тот же размер поможет, так как это устраняет затраты времени на выделение памяти.

Я не Java-человек, но мне было поручено выяснить эту проблему, и я пытаюсь выяснить, с чего начать. Любые советы с благодарностью!

Обновить
Я начал анализировать мусорные свалки с помощью -XX:+PrintGCDetails

Когда я замечаю это время от времени долгую загрузку, журналы gc сходят с ума. последний, который я сделал (на это ушло 25 секунд), у меня были строки журнала gc, такие как:

1720.267: [GC 1720.267: [DefNew: 27712K->16K(31104K), 0.0068020 secs] 281792K->254096K(444112K), 0.0069440 secs]
1720.294: [GC 1720.294: [DefNew: 27728K->0K(31104K), 0.0343340 secs] 281808K->254080K(444112K), 0.0344910 secs]

около 300 из них по одному запросу!!! Теперь я не совсем понимаю, почему это всегда GC'ng от ~28 м до 0 раз и снова.

4 ответа

Решение

Хотя я не запускал никаких приложений JRuby на Tomcat, я запускал приложения ColdFusion на различных серверах приложений J2EE, и у меня также были подобные проблемы.

В этих часто задаваемых вопросах вы увидите, что SOracle сообщает, что в 32-битной Windows максимальный размер кучи будет ограничен от 1,4 до 1,6 ГБ. Мне никогда не удавалось добиться стабильности на таком высоком уровне, и я подозреваю, что у вас аналогичная конфигурация.

Я предполагаю, что вашим запросам требуется много времени для выполнения ч / б с таким большим размером кучи, JVM выделила больше физической памяти, чем Windows, и, следовательно, Windows тратит много времени на подкачку страниц в и из памяти на диск, чтобы он мог обеспечить необходимый объем памяти для JVM.

Моя рекомендация, хотя и нелогичная, заключается в том, что вы на самом деле уменьшаете максимальный размер кучи примерно до 1,2 ГБ. Вы также можете увеличить минимальный размер, если заметите, что в обработке запросов приложения есть замедления, в то время как JVM должна запросить у Windows больше памяти, чтобы увеличить размер своей кучи, поскольку она заполняется несобранными объектами.

Часть вашей проблемы заключается в том, что вы, вероятно, голодаете все другие процессы для оперативной памяти. Мое общее правило для -Xms а также -Xmx являются следующими:

-Xms : <System_Memory>*.5
-Xmx : <System_Memeory>*.75

Таким образом, в системах с 4 ГБ это будет: -Xms2048m -Xmx3072mи в вашем случае я бы пошел с -Xms896m -Xmx1344

В дополнение к предыдущим ответам, вы также должны принять во внимание PermGen. PermGen не является частью кучи. с вашей текущей конфигурацией ваш процесс Java может составить до 1792 МБ, что является общим объемом вашей машины.

Я знаю, что уже выбран ответ, но все же, вот мое объяснение.

Прежде всего, в используемой командной строке вы уже зарезервировали 1536 мегабайт для кучи Java (-Xmx1536m) и 256 мегабайт для PermGen (-XX:MaxPermSize=256m). PermGen размещается отдельно от кучи Java и используется для хранения классов Java, загруженных в JVM.

Эти две области вместе уже составляют до 1792 мегабайт оперативной памяти.

Но в дополнение к этому, есть также RAM, необходимая для загрузки самой JVM (собственный код JVM) и RAM для хранения кода, сгенерированного компилятором JIT.

Я подозреваю, что все эти данные составляют виртуальный гигабайт объемом 2 ГБ, о котором вы упоминали.

Наконец, вы также должны принять во внимание другие вещи, которые работают на сервере и которые тоже нуждаются в оперативной памяти. Вы действительно не упомянули, сколько свопа используется на сервере. Это скажет вам, если машина обменивается, и это заставляет приложение реагировать медленно. Вы должны всегда предотвращать попадание JVM в своп. Гораздо лучше часто запускать сборщик мусора, чем выделять слишком много кучи и выменять часть кучи Java.

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