Для приложения, которое генерирует много недолговечного мусора и ничего долгоживущего, один подход, который может сработать, - это большая куча с почти всем этим молодым поколением и почти всем тем eden и владением всем, что переживает коллекцию YG больше, чем один раз.
Например (скажем, у вас был 32-битный JVM)
- 3072M куча (Xms и Xmn)
- 128 млн. Шт. (Т. Е. Xmn 2944 м.)
- MaxTenuringThreshold = 1
- SurvivorRatio = 190 (т. Е. Каждое пространство выживших составляет 1/192 от YG)
- TargetSurvivorRatio = 90 (т.е. заполнить выживших как можно больше)
Точные параметры, которые вы будете использовать для этой настройки, зависят от того, каков размер установившегося состояния вашего рабочего набора (т. Е. Сколько живого во время каждой коллекции). Размышления здесь явно противоречат нормальным правилам определения размера кучи, но тогда у вас нет приложения, которое ведет себя таким образом. Мысль заключается в том, что приложение в основном состоит из недолговечного мусора и небольшого количества статических данных, поэтому настройте jvm так, чтобы статические данные быстро передавались на хранение, а затем имели достаточно большой YG, чтобы их часто не собирали, часто минимизируя Частота пауз. Вам нужно будет многократно вертеть ручки, чтобы определить, какой размер вам подходит, и как он соотносится с размером паузы, которую вы получаете за каждую коллекцию. Например, вы можете найти более короткие, но более частые паузы YG.
Вы не говорите, как долго работает ваше приложение, но цель здесь состоит в том, чтобы вообще не иметь постоянных коллекций в течение жизни приложения. Конечно, это невозможно, но к этому стоит стремиться.
Однако в вашем случае важен не только алгоритм сбора данных, но и место, где выделяется память. Коллектор NUMA (совместимый только с коллектором пропускной способности и активированный с помощью переключателя UseNUMA) использует наблюдение, что объект часто используется исключительно тем потоком, который его создал, и, таким образом, выделяет память соответствующим образом. Я не уверен, на чем он основан в Linux, но он использует MPO (оптимизация размещения памяти) в Solaris, некоторые подробности в одном из блогов GC guys
Поскольку вы используете 64-битную jvm, убедитесь, что вы также используете CompressedOops.
Принимая во внимание скорость выделения объектов (возможно, какая-то научная библиотека?) И время жизни, вам следует уделить внимание повторному использованию объектов. Одним из примеров того, как библиотека делает это, является javalution StackContext
Наконец, стоит отметить, что GC-паузы - это не единственные паузы STW, вы можете запустить их со сборкой 6u21 для раннего доступа , в которой есть некоторые исправления для переключателей PrintGCApplicationStoppedTime и PrintGCApplicationConcurrentTime (которые эффективно печатают время на глобальном уровне). безопасная точка и время между этими безопасными точками). Вы можете использовать флаг tracesafepointstatistics, чтобы получить некоторое представление о том, что заставляет его нуждаться в безопасной точке (иначе ни один байт-код не выполняется ни одним потоком).