Первое, что я узнал о CMS, это то, что ей нужно больше памяти, чем другим сборщикам, на 25-50% больше - хорошая отправная точка. Это поможет вам избежать фрагментации, поскольку CMS не выполняет никакого уплотнения, как при остановке сборщиками мира. Во-вторых, делайте вещи, которые помогают сборщику мусора; Integer.valueOf вместо нового Integer, избавьтесь от анонимных классов, убедитесь, что внутренние классы не обращаются к недоступным вещам (частным во внешнем классе) и тому подобное. Чем меньше мусора, тем лучше. FindBugs и игнорирование предупреждений очень помогут в этом.
Что касается тюнинга, я обнаружил, что вам нужно попробовать несколько вещей:
-XX: + UseConcMarkSweepGC
Указывает JVM использовать CMS в штатном поколении.
Исправьте размер вашей кучи: -Xmx2048m -Xms2048m Это не позволяет GC выполнять такие вещи, как увеличение и уменьшение кучи.
-XX: + UseParNewGC
использовать параллельное вместо серийного сбора в молодом поколении. Это ускорит ваши второстепенные коллекции, особенно если у вас настроен очень большой молодой генерал. Большое молодое поколение, как правило, хорошо, но не стоит больше половины старого поколения.
-XX: ParallelCMSThreads = X
установить количество потоков, которые CMS будет использовать при выполнении действий, которые могут выполняться параллельно.
-XX: + CMSParallelRemarkEnabled примечание является последовательным по умолчанию, это может ускорить вас.
-XX: + CMSIncrementalMode позволяет приложению работать больше, проводя GC между фазами
-XX: + CMSIncrementalPacing позволяет JVM рассчитывать изменение частоты сбора данных с течением времени
-XX: CMSIncrementalDutyCycleMin = X Минимальное количество времени, затрачиваемое на GC
-XX: CMSIncrementalDutyCycle = X Начните с выполнения GC в этот% времени
-XX: CMSIncrementalSafetyFactor = X
Я обнаружил, что вы можете получить, как правило, низкое время паузы, если вы настроите его так, чтобы оно в основном всегда собиралось. Поскольку большая часть работы выполняется параллельно, в итоге вы получаете в основном регулярные предсказуемые паузы.
-XX: CMSFullGCsBeforeCompaction = 1
Это очень важно. Он говорит сборщику CMS всегда завершать сбор, прежде чем он начнет новый. Без этого вы можете столкнуться с ситуацией, когда он отбрасывает кучу работы и начинает снова.
-XX: + CMSClassUnloadingEnabled
По умолчанию CMS позволит вашему PermGen расти, пока не убьет ваше приложение через несколько недель. Это останавливает это. Ваш PermGen будет только расти, если вы используете Reflection, или неправильно используете String.intern, или делаете что-то плохое с загрузчиком классов, или несколькими другими вещами.
Коэффициент выживаемости и срок владения также можно использовать, в зависимости от того, есть ли у вас объекты с длительным или коротким сроком службы, а также от того, сколько объектов можно скопировать между пространствами выживших. Если вы знаете, что все ваши объекты будут слипаться, вы можете настроить оставшиеся в живых пространства нулевого размера, и все, что выживет в одной коллекции молодого поколения, будет немедленно заключено в аренду.