Агрессивная стратегия сборщика мусора

Я запускаю приложение, которое создает и забывает большое количество объектов, количество давно существующих объектов растет медленно, но это очень мало по сравнению с короткоживущими объектами. Это настольное приложение с требованиями высокой доступности, его нужно включать 24 часа в сутки. Большая часть работы выполняется в одном потоке, этот поток просто использует весь процессор, который может получить в свои руки.

В прошлом мы наблюдали следующее при большой нагрузке: Используемое пространство кучи медленно увеличивается, поскольку сборщик мусора собирает меньше, чем объем вновь выделенной памяти, размер используемой кучи медленно увеличивается и в конечном итоге прибывает рядом с указанной максимальной кучей. В этот момент сильно включится сборщик мусора и начнет использовать огромное количество ресурсов, чтобы не допустить превышения максимального размера кучи. Это замедляет работу приложения (легко в 10 раз медленнее), и в этот момент в большинстве случаев сборщик мусора удастся очистить мусор через несколько минут или выйдет из строя и выбросит OutOfMemoryException , оба они не совсем приемлемо.

Используемое оборудование представляет собой четырехъядерный процессор с как минимум 4 ГБ памяти под управлением 64-разрядной версии Linux, и все это мы можем использовать при необходимости. В настоящее время приложение в значительной степени использует одно ядро, которое большую часть времени использует одно ядро ​​/ поток.Остальные ядра в основном простаивают и могут использоваться для сборки мусора.

У меня есть ощущение, что сборщик мусора должен собирать более агрессивно на ранней стадии, задолго до того, как ему не хватит памяти. У нашего приложения нет проблем с пропускной способностью, требования к малому времени паузы немного важнее, чем пропускная способность, но гораздо менее важны, чем не приближаться к максимальному размеру кучи. Допустимо, если единственный занятый поток работает только на 75% от текущей скорости, если это означает, что сборщик мусора может не отставать от создания. Короче говоря, устойчивое снижение производительности лучше, чем внезапное падение, которое мы наблюдаем сейчас.

Я внимательно прочитал Java SE 6 HotSpot [tm] Virtual Machine Garbage Collection Tuning , что означает, что я хорошо понимаю параметры, однако мне все еще трудно выбрать правильные настройки, так как мои требования являются немного отличается от того, что обсуждается в статье.

В настоящее время я использую ParallelGC с опцией -XX: GCTimeRatio = 4 . Это работает немного лучше, чем настройка по умолчанию для соотношения времени, но я чувствую, что GC может работать больше с этой настройкой, чем он.

Для мониторинга я в основном использую jconsole и jvisualvm.

Я хотел бы знать, какие варианты сборки мусора вы рекомендуете для описанной выше ситуации. Также на какие выходные данные отладки GC я могу взглянуть, чтобы лучше понять горлышко бутылки.

РЕДАКТИРОВАТЬ: Я понимаю, что здесь очень хороший вариант - создать меньше мусора, это то, что мы действительно рассматриваем, однако я хотел бы знать, как мы можем решить эту проблему с помощью настройки GC, поскольку это то, что мы можем сделать намного проще и быстрее, чем изменение больших объемов исходного кода. Также я запускал различные профилировщики памяти, и я понимаю, чем используется мусор, и я знаю, что он состоит из объектов, которые можно собрать.

Я использую:

java version "1.6.0_27-ea"
Java(TM) SE Runtime Environment (build 1.6.0_27-ea-b03)
Java HotSpot(TM) 64-Bit Server VM (build 20.2-b03, mixed mode)

С параметрами JVM:

-Xmx1024M and -XX:GCTimeRatio=4 

Изменить в ответ на комментарии Мэтта: Большая часть памяти (и ЦП) уходит на создание объектов, которые представляют текущую ситуацию. Некоторые из них будут отброшены сразу же, поскольку ситуация быстро изменится, некоторые другие будут иметь средний срок службы, если какое-то время не будет обновляться.

33
задан Ravindra babu 24 May 2016 в 12:43
поделиться