Дуже великі розміри купи Java [закрито]


76

Хто-небудь має досвід використання дуже великих куп, розміром 12 ГБ або більше в Java?

  • Чи робить GC програму непридатною для використання?
  • Які параметри GC ви використовуєте?
  • Який JVM, Sun або BEA для цього найкраще підійде?
  • Яка платформа, Linux чи Windows, працює ефективніше за таких умов?
  • У випадку з Windows, чи є різниця в продуктивності між 64-розрядною системою Vista та XP при такому великому навантаженні пам'яті?

Відповіді:


74

Якщо ваш додаток не є інтерактивним, і GC-паузи не є проблемою для вас, не повинно виникнути жодних проблем для 64-розрядної Java, щоб обробляти дуже великі купи, навіть у сотні ГБ. Ми також не помітили жодних проблем зі стабільністю ні в Windows, ні в Linux.

Однак, коли вам потрібно тримати паузи GC низькими, все стає по-справжньому неприємним:

  1. Забудьте про пропускну здатність за замовчуванням, зупиніть світ GC. Це призупинить програму на кілька десятків секунд для помірних куп (<~ 30 ГБ) і кілька хвилин для великих (> ~ 30 ГБ). І купівля швидших модулів DIMM не допоможе.

  2. Найкращий вибір - це, мабуть, колектор CMS, включений -XX: + UseConcMarkSweepGC. Збирач сміття CMS зупиняє програму лише на початковій фазі маркування та фазах повторного маркування. Для дуже маленьких куп, як <4 Гб, це, як правило, не проблема, але для програми, яка створює багато сміття і велику купу, фаза перемаркірування може зайняти досить тривалий час - зазвичай набагато менше, ніж повна зупинка світу , але все одно може бути проблемою для дуже великих куп.

  3. Коли збирач сміття CMS недостатньо швидкий, щоб закінчити роботу, перш ніж заповнене покоління заповниться, він повертається до стандартного GC для зупинки світу. Очікуйте ~ 30 або більше секунд довгих пауз для купи розміром 16 ГБ. Ви можете спробувати уникнути цього, зберігаючи якнайменше низький рівень вироблення сміття у вашому додатку. Зауважте, що чим більша кількість ядер, на яких працює ваш додаток, тим більшою стає проблема, оскільки система управління вмістом використовує лише одне ядро. Очевидно, остерігайтеся, немає гарантії, що система управління вмістом не повернеться до колектора STW. А коли це відбувається, це зазвичай трапляється при пікових навантаженнях, і ваша програма мертва протягом декількох секунд. Можливо, ви не хотіли б підписувати SLA для такої конфігурації.

  4. Ну, є та нова річ G1. Він теоретично розроблений, щоб уникнути проблем із системою управління вмістом, але ми спробували це і помітили, що:

    • Його пропускна здатність гірша, ніж у CMS.
    • Теоретично йому слід уникати першого збору популярних блоків пам'яті, проте незабаром він досягає стану, коли майже всі блоки є "популярними", і припущення, на яких він базується, просто перестають працювати.
    • Нарешті, для G1 все ще існує запасний варіант „зупинки світу”; запитайте у Oracle, коли цей код повинен бути запущений. Якщо вони кажуть "ніколи", запитайте їх, чому там код? Тож IMHO G1 насправді не змушує величезну проблему купи Java зникнути, вона лише робить її (можливо) трохи меншою.
  5. Якщо у вас є гроші за великий сервер з великою пам’яттю, ви, мабуть, також маєте гроші за хорошу, комерційну апаратно прискорену, беззмінну технологію GC, подібну до тієї, яку пропонує Azul. У нас є один із їхніх серверів з 384 ГБ оперативної пам’яті, і він справді чудово працює - без пауз, 0-рядків коду зупинки світу в GC.

  6. Напишіть ту прокляту частину вашого додатку, яка вимагає багато пам’яті на C ++, як LinkedIn при обробці соціальних графіків. Ви все одно не уникнете всіх проблем, роблячи це (наприклад, фрагментація купи), але, безумовно, було б простіше тримати паузи низькими.


1
5. Навряд чи. 192 Мб машини становить близько 15 тис. Євро. Ціни на Azul - це підприємництво, чи не так?
Stephan Eggermont

1
Це легко найкраще резюме тут. Я б додав дві речі: (1) CMSInitiatingOccupancyFraction може пом'якшити проблему "CMS не може закінчитися до заповнення старого покоління", але (2) на відміну від колектора пропускної здатності, CMS не ущільнює купу, тому фрагментація зазвичай примушує STW Зрештою GC.
jbellis

@StephanEggermont ви мали на увазі машину на 192 ГБ , так?
ом-ном-ном

@ om-nom-nom так, це правильно. Не вдається редагувати коментарі на день пізніше, на жаль
Стефан Еггермонт

17

Я є генеральним директором Azul Systems, тому я, очевидно, необ'єктивно вважаю цю тему! :) Це сумно...

Технічний директор Azul, Гіл Тене, має хороший огляд проблем, пов’язаних зі збиранням сміття, та огляд різних рішень у своїй презентації « Розуміння збору сміття Java та те, що ви можете зробити з цим» , а в цій статті є додаткові подробиці: http: // www.infoq.com/articles/azul_gc_in_detail .

Збірник сміття Azul C4 у нашому Zing JVM одночасно паралельний і одночасний, і використовує один і той же механізм GC як для нового, так і для старого покоління, працюючи одночасно та ущільнюючи в обох випадках. Найголовніше, що у C4 немає зупинки світу. Все ущільнення виконується одночасно з запущеним додатком. У нас є клієнти, що працюють дуже великими (сотні Гбайт), з гіршими випадками часу паузи GC <10 мсек, і залежно від програми часто менше, ніж 1-2 мсек.

Проблема CMS і G1 полягає в тому, що в якийсь момент пам'ять купи Java повинна бути ущільнена, і обидва ці збирачі сміття зупиняють світ / STW (тобто призупиняють програму) для виконання ущільнення. Таким чином, хоча CMS та G1 можуть виштовхувати паузи STW, вони не усувають їх. Однак C4 Azul повністю усуває паузи STW, і тому Zing має такі низькі паузи GC навіть для гігантських розмірів купи.


29
Після приблизно 6 електронних листів туди-сюди з одним із ваших продавців я відмовився від отримання інформації про ціни. Рішення, яке ви навіть не можете оцінити, не є рішенням.
Чад Вілсон,

14

У нас є програма, на яку ми виділяємо 12-16 Гб, але вона насправді досягає лише 8-10 під час нормальної роботи. Ми використовуємо Sun JVM (пробували IBM, і це було певною катастрофою, але це просто могло бути незнанням з нашого боку ... У мене є друзі, які клянуться цим - які працюють в IBM). Поки ви надаєте додаткові кімнати для дихання, JVM може обробляти великі розміри купи з не надто великим ГК. Багато «зайвої» пам'яті є ключовим фактором.
Linux майже завжди стабільніший, ніж Windows, і коли він не стабільний, набагато легше зрозуміти, чому. Solaris також твердий, і ви також отримуєте DTrace :) Чому з такими видами навантажень ви б використовували Vista або XP? Ви просто просите неприємностей. Ми не робимо нічого химерного з параметрами GC. Ми встановлюємо мінімальний розподіл рівним максимальному, тому він не постійно намагається змінити розмір, але це все.


2
Я б не сказав, що Linux був стабільнішим за Windows, проте дуже можливо, що тест Sun - це JVM більше на модулі та linex, ніж на Windows.
Ян Рінгроуз,

9

Я використав понад 60 ГБ розмірів купи у двох різних додатках під Linux та Solaris відповідно, використовуючи 64-розрядні версії (очевидно) Sun 1.6 JVM.

Я ніколи не стикався з проблемами збору сміття з додатком на базі Linux, за винятком випадків, коли піднімався вгору біля обмеження розміру купи. Щоб уникнути проблем з розбиттям, властивих цьому сценарію (занадто багато часу, витраченого на збір сміття), я просто оптимізував використання пам’яті у всій програмі, щоб пікове використання було приблизно на 5-10% нижче граничного розміру купи 64 ГБ.

Однак із іншим додатком, що працює під управлінням Solaris, я зіткнувся зі значними проблемами зі збиранням сміття, через що потрібно було багато налаштувати. Це складалося насамперед із трьох кроків:

  1. Увімкнення / примусове використання паралельного збирача сміття за допомогою опцій -XX: + UseParallelGC -XX: + UseParallelOldGC JVM, а також управління кількістю потоків GC, що використовуються за допомогою параметра -XX: ParallelGCThreads. Докладніше див. У розділі " Налаштування сміття для віртуальної машини Java SE 6 HotSpot ".

  2. Широке і, здавалося б, смішне встановлення місцевих змінних у "нуль" після того, як вони більше не потрібні. Більшість із них були змінними, які мали бути придатними для збору сміття після виходу з поля дії, і вони не були ситуацією витоку пам’яті, оскільки посилання не були скопійовані. Однак ця стратегія "тримання в руках" для сприяння збору сміття була незрозуміло необхідною з якоїсь причини для цієї програми на відповідній платформі Solaris.

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

Три вищезазначені кроки дозволили зберегти цю програму та працювати продуктивно на рівні близько 60 ГБ купи, замість того, щоб вирости з-під контролю до обмеження розміру купи 128 ГБ, яке було на місці. Зокрема, паралельний збирач сміття був дуже корисним, оскільки основні цикли збирання сміття дорогі, коли багато об’єктів, тобто час, необхідний для основного збору сміття, залежить від кількості об’єктів у купі.

Я не можу коментувати інші проблеми, пов'язані з платформою, у цьому масштабі, а також я не використовував JVM, що не належать до Sun (Oracle).


8

12 Гб не повинно бути проблемою з гідною реалізацією JVM, такою як Sun's Hotspot. Я б порадив вам використовувати збірник одночасних позначок і розгортки (-XX: + UseConcMarkSweepGC) під час використання VM від SUN.

ОС не повинна мати великого значення для продуктивності GC.

Звичайно, вам знадобиться 64-розрядна ОС і машина з достатньою кількістю фізичної оперативної пам'яті.


7

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

jmap -heap:format=b pid

... і як це відповідає на актуальне питання?
ddimitrov

3
тому що при такому великому купі варто шукати зменшення розміру пам'яті, а також оптимізацію JVM
jlintz

Погодьтеся. Якщо у вас немає спеціального додатку, вам не знадобиться 12 ГБ купи. Це, як правило, вказує на погану практику кодування, наприклад, завантаження великих речей в оперативну пам’ять відразу, які ви повинні замість них передавати. Робіть це правильно, і ваша програма теж добре масштабується. Робіть це неправильно, і вам доведеться продовжувати збільшувати розмір купи, оскільки ваш додаток стає зайнятішим / обробляє більші обсяги даних.
Франс

2

Як згадувалося вище, якщо у вас є неінтерактивна програма, збирач сміття за замовчуванням (ущільнюючий) повинен добре працювати. Якщо у вас є інтерактивна програма, і ви (1) не розподіляєте пам’ять швидше, ніж GC може встигати, і (2) не створюєте занадто великі тимчасові об’єкти (або колекції об’єктів) (відносно загальної кількості максимальна пам’ять JVM), щоб GC міг обійтись, тоді CMS для вас.

Ви стикаєтесь з проблемами, якщо у вас є інтерактивна програма, де в ГК недостатньо дихальної кімнати. Це правда, незалежно від того, скільки у вас пам’яті, але чим більше у вас пам’яті, тим гірше вона стає. Це тому, що коли у вас недостатньо пам’яті, у CMS закінчується пам’ять, тоді як ущільнювальні GC (включаючи G1) призупиняють все, поки вся пам’ять не буде перевірена на сміття. Ця пауза зупинки світу стає більшою, чим більше у вас пам’яті. Повірте, ви не хочете, щоб ваші сервлети зупинялися більше хвилини. Я написав докладну відповідь StackOverflow про ці паузи в G1.

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

Але, звичайно, Zing не є безкоштовним, а його спеціальний соус запатентований. Якщо у вас є набагато більше часу, ніж грошей, спробуйте переписати програму, щоб використовувати кластер JVM.

На горизонті Oracle працює над високопродуктивним ГХ для багатогігабайтних куп. Однак на сьогодні це не варіант.


1

Якщо ви перейдете на 64-розрядну версію, ви будете використовувати більше пам'яті. Покажчики стають 8 байтами замість 4. Якщо ви створюєте багато об'єктів, це можна помітити, оскільки кожен об'єкт є посиланням (покажчиком).

Нещодавно я виділив 15 Гб пам’яті в Java, використовуючи Sun 1.6 JVM, без проблем. Хоча все це виділяється лише один раз. Після початкового обсягу виділяється або звільняється не набагато більше пам'яті. Це було на Linux, але я думаю, Sun JVM буде працювати так само добре на 64-розрядної Windows.


1

Спробуйте запустити visualgc проти свого додатка. Це інструмент візуалізації купи, який є частиною завантаження jvmstat за адресою http://java.sun.com/performance/jvmstat/

Це набагато простіше, ніж читання журналів GC.

Це швидко допомагає зрозуміти, як працюють частини (покоління) купи. Незважаючи на те, що загальна вага купи може становити 10 Гб, різні частини купи будуть значно меншими. ГК в районі купи Едему відносно дешеві, тоді як повні ГК у старому поколінні дорогі. Розмір вашої купи так, щоб Едем був великим, а старе покоління навряд чи колись торкнувся, є хорошою стратегією. Це може призвести до дуже великої загальної купи, але, блін, якщо JVM ніколи не торкається сторінки, це просто віртуальна сторінка, і вона не повинна займати оперативну пам’ять.


1

Пару років тому я порівняв JRockit та Sun JVM для купи 12G. JRockit переміг, а підтримка величезних сторінок Linux зробила наш тестовий запуск на 20% швидшим. YMMV, оскільки наш тест був дуже процесором / пам’яттю, і був переважно однопоточним.


Яка версія Java була такою, і чи встигли б ви це зробити сьогодні? Цифри були б дуже цікаві.
Thorbjørn Ravn Andersen

Я більше не консультую одну і ту ж компанію, тому у мене навіть немає середовища, щоб спробувати це. Це був JDK1.5 JRockit, IIRC.
ShabbyDoo

1

ось стаття про gc ІЗ одного з Java Champions - http://kirk.blog-city.com/is_your_concurrent_collector_failing_you.htm

Кірк, автор пише "Надішліть мені свої журнали GC

В даний час я зацікавлений у вивченні журналів GC Sun JVM. Оскільки ці журнали не містять актуальної для бізнесу інформації, це повинно полегшити занепокоєння щодо захисту інформації про протаріати. Все, що я прошу, щоб у журналі ви згадували ОС, повну інформацію про версію JRE та будь-які перемикачі командного рядка, пов’язані з купою / gc, які ви встановили. Я також хотів би знати, чи використовуєте ви Grails / Groovey, JRuby, Scala чи щось інше, ніж або вздовж бічної Java. Найкращим налаштуванням є -Xloggc :. Зверніть увагу, що цей журнал не перевертається, коли він досягає обмеження розміру вашої ОС. Якщо я знайду щось цікаве, я із задоволенням дам вам дуже швидкий конспект у відповідь. "


Будь ласка, оновіть посилання на kirk.blog-city.com/is_your_concurrent_collector_failing_you.htm
Claes


0

Максимальна пам’ять, на яку може адресувати XP, - 4 гіга ( тут ). Тож ви можете не захотіти використовувати для цього XP (використовуйте 64-бітну ОС).


Або скористайтеся 64-розрядною версією XP. ;)
Тайлер Міллікан

Це не обмеження XP, це обмеження будь-якої 32-розрядної ОС, яка не використовує PAE.
ТМ.

1
Це обмеження для всіх 32-розрядних ОС, навіть тих, які використовують PAE.
Джеймс,

@james, Якщо ви використовуєте PAE, ви побачите цілі 4 ГБ, якщо у вас немає PAE, ви не побачите пристроїв, які відображаються на пам'ять (графічні карти тощо).
Мілхус,

0

Sun вже деякий час має 64-розрядний jvm itanium, хоча itanium не є популярним напрямком. 64-розрядні JVM-програми Solaris та Linux повинні бути тим, чим ви повинні бути.
Кілька питань

1) чи стабільна ваша програма?
2) Ви вже тестували програму в 32-розрядному JVM?
3) чи нормально запускати кілька JVM на одному вікні?

Я очікував би, що приблизно за рік чи близько 64-розрядна ОС з Windows стане стабільною, але до цього моменту краще було б поставити програму solaris / linux.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.