Сколько раз мне приходилось настраивать GC, чтобы вылечить приложение, у которого время от времени случается приступ, и оно перестает временно выполнять свои функции. Работа, скажу, не самая занимательная и требует хорошего знания матчасти. В данном топике я опишу какие еще есть способы решения данной проблемы.
Если ваш java Heap больше нескольких гигов (в зависимости от требований приложения), то никакие настройки GC вам не помогут. Будь-то CMS, JRocket или даже уже сто лет разрабатываемый G1, ничего вас в этом случае не спасет. Хотя нет, есть на горизонте один продукт: виртуальная java машина от Azul. Но это решение опять же платное, требует проприетарного железа либо виртуализации, которая опять же дает свои накладные расходы. Кому интересно, можно почитать чуть-чуть больше в комментариях к моему посту GC tuning. Что же может сделать обычный java разработчик, чтобы вылечить приложение, требующее значительного объема памяти?
Первым делом, конечно же стоит выяснить есть ли утечки памяти. Может они на столько велики или память используется настолько не эффективно, что убрав утечку, вы автоматически решите свои проблемы.
Если у вас есть возможность периодически рестартить ваше приложение или есть интервал времени, когда вы можете вызвать Full GC. При определенном паттерне работы с памятью, когда вы сможете поддерживать небольшой размер молодого поколения и иметь разумный поток объектов попадающих в старое поколение, то можно увеличить размер вашего Heap до такого значения, что сборки в Old Gen, будут случаться только в те моменты, когда вы это можете позволить. Но данный вариант больше похож на хак, чем на мейнстрим.
Еще один очень популярный прием уменьшения пауз GC это разбиение вашего приложения на несколько частей, которые будут запускаться в разных JVM. Большинство в данный момент и идут по этой дороге. Это, действительно, хорошее решение, если ваша система слабо связанна и хорошо делится логически. Но любое распределение так или иначе значительно усложняет вашу архитектуру и замедляет взаимодействие, так что оно подойдет не для любого приложения.
Также как вариант можно рассмотреть удаленный кэш написанный на чем-нибудь безхиповом. Например, memcached. Но тут опять же, как и в предыдущем решении, мы получаем распределенную систему и замедление работы приложения, так как теперь объекты надо будет сериализовать и передавать через сокеты. В довесок мы получаем компонент, написанный не на java, поддержка которого для рядового java программиста может стать затруднительной.
Довольно долго на этом список возможных решений практически заканчивался, оставляя java программистов в пичале. Но в последнее время все чаще начинает всплывать решение на основе так называемых direct bufffer, когда дополнительная память выделяется прямо внутри java процесса, но вне heap, что позволяет иметь приложение, написанное полностью на java, легко использовать память в десятки гигабайт и избежать проблем, возникающих при распределении. Подробнее об этом подходе можно прочитать в статье Java Off-Heap Cache.
Так же участвуйте в опросе на эту тему.
Если ваш java Heap больше нескольких гигов (в зависимости от требований приложения), то никакие настройки GC вам не помогут. Будь-то CMS, JRocket или даже уже сто лет разрабатываемый G1, ничего вас в этом случае не спасет. Хотя нет, есть на горизонте один продукт: виртуальная java машина от Azul. Но это решение опять же платное, требует проприетарного железа либо виртуализации, которая опять же дает свои накладные расходы. Кому интересно, можно почитать чуть-чуть больше в комментариях к моему посту GC tuning. Что же может сделать обычный java разработчик, чтобы вылечить приложение, требующее значительного объема памяти?
Первым делом, конечно же стоит выяснить есть ли утечки памяти. Может они на столько велики или память используется настолько не эффективно, что убрав утечку, вы автоматически решите свои проблемы.
Если у вас есть возможность периодически рестартить ваше приложение или есть интервал времени, когда вы можете вызвать Full GC. При определенном паттерне работы с памятью, когда вы сможете поддерживать небольшой размер молодого поколения и иметь разумный поток объектов попадающих в старое поколение, то можно увеличить размер вашего Heap до такого значения, что сборки в Old Gen, будут случаться только в те моменты, когда вы это можете позволить. Но данный вариант больше похож на хак, чем на мейнстрим.
Еще один очень популярный прием уменьшения пауз GC это разбиение вашего приложения на несколько частей, которые будут запускаться в разных JVM. Большинство в данный момент и идут по этой дороге. Это, действительно, хорошее решение, если ваша система слабо связанна и хорошо делится логически. Но любое распределение так или иначе значительно усложняет вашу архитектуру и замедляет взаимодействие, так что оно подойдет не для любого приложения.
Также как вариант можно рассмотреть удаленный кэш написанный на чем-нибудь безхиповом. Например, memcached. Но тут опять же, как и в предыдущем решении, мы получаем распределенную систему и замедление работы приложения, так как теперь объекты надо будет сериализовать и передавать через сокеты. В довесок мы получаем компонент, написанный не на java, поддержка которого для рядового java программиста может стать затруднительной.
Довольно долго на этом список возможных решений практически заканчивался, оставляя java программистов в пичале. Но в последнее время все чаще начинает всплывать решение на основе так называемых direct bufffer, когда дополнительная память выделяется прямо внутри java процесса, но вне heap, что позволяет иметь приложение, написанное полностью на java, легко использовать память в десятки гигабайт и избежать проблем, возникающих при распределении. Подробнее об этом подходе можно прочитать в статье Java Off-Heap Cache.
Так же участвуйте в опросе на эту тему.