Як зменшити збій Java-конкурента та надмірний режим gc

У Java помилка паралельного режиму означає, що конкуруючий колектор не зміг звільнити достатньо місця постійного та постійного типу пам'яті, і він повинен відмовитись і дозволити gc повністю зупинити світ gc. кінцевий результат може бути дуже дорогим.

може бути

Я розумію цю концепцію, але ніколи не мав хорошого всебічного розуміння A) що може спричинити несправність одночасно і B) Яке рішення ?.

Така невизначеність призводить до того, що я пишу/виправляю неполадки без зайвих пропозицій, і мені часто доводиться робити покупки навколо цих прапорів продуктивності від Foo до Bar без особливих причин, мені просто потрібно спробувати.

Я хотів би дізнатися у розробників тут, яким є ваш досвід? Якщо ви зіткнулися з проблемою продуктивності, що було причиною та як ви підійшли до неї?

Якщо у вас є рекомендації щодо кодування, будь ласка, не будьте занадто загальними. Дякую!

4 відповіді

Перше, що я дізнався про CMS, це те, що їй потрібно більше пам'яті, ніж іншим колекторам, приблизно на 25-50% більше - це гарна відправна точка. Це допомагає уникнути фрагментації, оскільки система управління вмістом не робить жодного ущільнення, наприклад, зупинення глобального збору. По-друге, робіть справи, які допомагають збиральнику сміття; Integer.value Замість нового Integer, позбудьтеся анонімних класів, переконайтесь, що внутрішні класи не мають доступу до недоступних речей (приватних у зовнішньому класі). Чим менше сміття, тим краще. FindBugs і не ігнорування попереджень дуже допоможуть у цьому.

Що стосується налаштування, я виявив, що вам потрібно спробувати кілька речей:

Розповідає JVM про використання CMS у жанрі, що передається.

Правильний розмір ворсу: -Xmx2048m -Xms2048m Це заважає GC робити такі дії, як збільшення та зменшення купи.

Використовуйте паралельну замість серійної колекції у молодого покоління. Це прискорить ваші незначні колекції, особливо якщо у вас встановлена ​​дуже велика молода стать. Велике молоде покоління, як правило, добре, але не перевищує половини старого статі.

встановити кількість потоків, які система керування вмістом використовуватиме, виконуючи паралельні дії.

-XX: + CMSParallelRemarkEnabled зауваження за замовчуванням є послідовним, це може пришвидшити вас.

-XX: + CMSIncrementalMode дозволяє додатку працювати довше, перемикаючи GC між фазами

-XX: + CMSIncrementalPacing дозволяє JVM змінювати зміну частоти збору з часом

-XX: CMSIncrementalDutyCycleMin = X Мінімальна кількість часу, проведеного в GC

-XX: CMSIncrementalDutyCycle = X Почніть з GC цього% часу

-XX: CMSIncrementalSafetyFactor = X

Я виявив, що зазвичай можна отримати короткі періоди перерви, якщо їх налаштувати так, щоб вони завжди збиралися. Оскільки більшість робіт виконуються паралельно, ви зазвичай досягаєте передбачуваних перерв.

-XX: CMSFullGCsBeforeCompaction = 1

Це дуже важливо. Він повідомляє колектору CMS завжди завершувати колекцію перед початком нової колекції. Без цього ви можете потрапити в ситуацію, коли кинете багато роботи і почнете спочатку.

За замовчуванням CMS дозволить PermGen рости, поки не вб’є вашу програму через кілька тижнів. Це зупиняється. Ваш PermGen збільшиться лише в тому випадку, якщо ви використовуєте Reflection або неправильно використовуєте String.intern або робите щось не так із завантажувачем класу чи щось інше.

Виживший також може бути відтворений залежно від того, чи є у вас довгі або короткі об'єкти життя, і скільки коштує копіювати об'єкт між місцями виживання, з якими ви можете жити. Якщо ви знаєте, що всі ваші об’єкти залишаться навколо, ви можете налаштувати нульові розміри просторів виживання, і все, що виживе в молодій жанровій колекції, буде негайно доступним.

Помилки паралельного режиму можна уникнути, збільшивши кількість генерації афілійованих осіб, або ініціювавши збір CMS до меншої потужності, встановивши для CMSInitiatingOccupancyFraction нижче значення

Однак, якщо у вашому додатку дійсно спостерігається витік пам'яті, ви просто купуєте час.

Якщо вам потрібна швидка перезавантаження та відновлення і ви віддаєте перевагу «швидкому» підходу, я б радив взагалі не використовувати CMS. Я би бився з '-XX: + UseParallelGC'.

Паралельний збирач сміття (UseParallelGC) видає виняток, який не вистачає пам’яті, якщо надто багато часу він зібрав невелику кількість з купи. Щоб уникнути цього винятку, ви можете збільшити розмір дампа. Ви також можете встановити параметри -XX: GCTimeLimit = обмеження часу та -XX: GCHeapFreeLimit = пробіл

Іноді OOM досить швидко і був убитий, іноді страждав протягом тривалого часу (останній період був більше 10 годин).

Мені здається, що витоки пам'яті є корінням ваших проблем.

Помилка CMS не спричинить (як я розумію) OOM. Навпаки, трапляється помилка CMS, оскільки JVM повинна робити занадто багато колекцій занадто швидко, і CMS не може встигати. Ситуація, коли за короткий проміжок часу відбувається багато циклів збору, це коли ваш звалище майже заповнене.

Справді довгий час шуму звучить дивно. але теоретично можливо, якщо ваша машина жахливо рухається. Однак тривалий період повторення КГ є цілком правдоподібним, якщо ваш смітник майже заповнений.

Ви можете налаштувати GC на падіння, коли дамп 1) у повному розмірі та 2) все ще близький до повного після завершення повного GC. Спробуйте зробити це, якщо ви цього ще не зробили. Це не допоможе вирішити проблеми, але принаймні ваш JVM швидко отримає OOM, що дозволить швидше перезапустити та відновити службу.

РЕДАГУВАТИ - варіант зробити це --XX: GCHeapFreeLimit = nnn, де nnn - це число від 0 до 100, що дає мінімальний відсоток купи, який повинен бути вільним після GC. За замовчуванням - 2. Опція вказана на сторінці під назвою "Найповніший список опцій -XX для Java 6 JVM". (Там перелічено безліч опцій -XX, які не відображаються в документації Sun. На жаль, на цій сторінці представлено детальну інформацію про те, що саме роблять ці параметри.)

Ви, мабуть, повинні почати шукати, чи немає в додатку/веб-програмі витоків пам'яті. Якщо так, ваші проблеми не зникнуть, якщо їх не буде знайдено та виправлено. У довгостроковій перспективі обробка параметрів Hotspot GC не виправить витоки пам’яті.