Максимальный размер кучи 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.