GC крутится все время, несмотря на много свободной кучи

У меня есть приложение, работающее с -mx7000m, Я вижу, что выделено 5,5 ГБ кучи. Тем не менее, по некоторым причинам, это GCing постоянно, и, будучи CMS, он оказывается довольно загруженным процессором. Итак, у него уже выделено 5,5 ГБ кучи, но каким-то образом он затрачивает все процессорное время, пытаясь сохранить используемую кучу как можно меньше, около 2 ГБ, а остальные 3,5 ГБ выделяются JVM, но не используются.

У меня есть несколько серверов с точно такой же конфигурацией, и 2 из 5 ведут себя так. Чем это можно объяснить?

Это Java 6, флаги: -server -XX:+PrintGCDateStamps -Duser.timezone=America/Chicago -Djava.awt.headless=true -Djava.io.tmpdir=/whatever -Xloggc:logs/gc.log -XX:+PrintGCDetails -mx7000m -XX:MaxPermSize=256m -XX:+UseConcMarkSweepGC

1 ответ

Пороговое значение по умолчанию для запуска CMS GC составляет 70% (в Java 6). Практическое правило заключается в том, что размер кучи должен быть примерно в 2,5 раза больше, чем куча, используемая после полного GC (но ваш вариант использования, вероятно, будет другим)

Так что в вашем случае, скажем, у вас есть

- 2.5 GB of young generation space
- 3 GB of tenured space.

Когда вы зарезервировали пространство, достигшее 70% или ~2,1 ГБ, начнется очистка региона.

Настройка заключается в -XX:CMSInitiatingOccupancyFraction=70

Однако, если вы хотите уменьшить влияние GC, проще всего создать меньше мусора. т. е. используйте профилировщик памяти и убедитесь, что скорость выделения минимально возможна. Ваша система будет работать по-другому, если вы создаете столько мусора, сколько процессоры могут обработать, скажем, 100 МБ / с или 1 МБ / с или менее.

Причина, по которой у вас могут быть разные серверы, работающие по-разному, поскольку относительные размеры региона могут быть разными, скажем, у вас есть 0,5 молодых и 5,0 ГБ, но вы не должны этого видеть. Разница может быть только в том, насколько занята машина, когда вы запускаете процесс, или в том, что он делал с тех пор.

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