Сборка мусора Java G1 в производстве

91

Поскольку Java 7 по умолчанию будет использовать новую сборку мусора G1, сможет ли Java обрабатывать на порядок большую кучу без предполагаемого «разрушительного» времени паузы сборщика мусора? Кто-нибудь действительно внедрил G1 в производство, каков был ваш опыт?

Честно говоря, я видел действительно длинные паузы сборщика мусора только в очень больших кучах, намного больше, чем на рабочей станции. Чтобы прояснить мой вопрос; откроет ли G1 шлюз до кучи в сотни гб? Туберкулез?

Benstpierre
источник
16
Хотя его можно перефразировать более конкретно, это не ужасный вопрос. Я действительно хочу, чтобы люди объяснялись лучше, чем «Не вопрос», при закрытии голосования.
Bill K
Я не голосовал за закрытие, но мне хотелось, чтобы OP более объективно детализировал свои претензии к текущему GC. Кроме того, «Java» - это язык, в то время как он говорит о реализации, и я не знаю, что означает «внедрение G1 в производство», особенно с учетом будущего времени в остальной части вопроса. Если это будет на Java 7, наверняка никто не использовал его в производстве?
Паскаль Куок,
6
@Pascal G1 был экспериментальной функцией, доступной в JDK с момента обновления 14 для JDK 6. Под «внедрением G1 в производство», я думаю, он имел в виду его фактическое использование, не так уж и сложно понять. И хотя я согласен с тем, что G1 является частью JDK 7, а не Java, поиск Java 7 в Google возвращает домашнюю страницу JDK 7 в качестве первого результата, и оба термина часто используются как взаимозаменяемые. @Benju Я бы не стал доверять результатам, полученным с помощью G1 на текущем JDK, поскольку он экспериментальный, многие вещи могут измениться с этого момента до официального выпуска.
teto
2
Кажется, что JDK 7, включая обновления 1,2 и 3, по умолчанию не использует G1 gc. Вы можете проверить это с помощью jinfo -flag UseG1GC pid
Джордж

Ответы:

34

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

Сборка мусора - это уже не простая сделка типа «Эй, он полный, давайте переместим все сразу и начнем заново» - это фантастически сложная многоуровневая фоновая многопоточная система. Он может выполнять большую часть своего обслуживания в фоновом режиме без каких-либо пауз, а также использует знания об ожидаемых шаблонах системы во время выполнения, чтобы помочь - например, если предположить, что большинство объектов умирает сразу после создания и т. Д.

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

РЕДАКТИРОВАТЬ:

при перечитывании мне пришло в голову, что я использую Java ежедневно - Eclipse, Azureus и разрабатываемые мной приложения, и прошло ДЛИННОЕ ВРЕМЯ с тех пор, как я увидел паузу. Небольшая пауза, но вообще любая пауза.

Я видел паузы, когда я щелкаю правой кнопкой мыши по проводнику Windows или (иногда) когда подключаю определенное USB-оборудование, но с Java - вообще нет.

GC все еще проблема для кого-то?

Билл К
источник
Согласитесь, я видел паузы сборщика мусора только тогда, когда я намеренно или случайно спровоцировал их с помощью параллельного кода, создающего мусор ...
mikera
28
Да, сборщик мусора по-прежнему является серьезной проблемой, когда вы начинаете иметь дело с большими кучами (> 16 ГБ), особенно с большими постоянными поколениями.
Алхимик
2
@ the-alchemist вау, я видел ваш комментарий мимоходом несколько раз, и меня просто поразило, что вы сказали 16 ГБ !! Хотя я абсолютно уверен, что вы правы, что это может вызвать огромные задержки, я хочу убедиться, что вы отключили ВСЕ подкачки. В системе с большой памятью любая подкачка java полностью убьет вашу систему (потому что GC очень недружелюбен к подкачке). Я уверен, что вы уже это сделали, но я просто хотел упомянуть об этом - потому что это будет иметь огромное значение. Я никогда не видел ПК с таким количеством оперативной памяти - сколько у вас? 32г?
Билл К.
8
Да, сборщики мусора проблематичны для сервисов, поскольку именно они ОЧЕНЬ сложно улучшить лимиты TP99.9 (и выше). В частности, сборщики мусора «старого поколения» могут стать смертельной ловушкой, которая практически останавливает JVM (и сервис) на несколько секунд; а для служб, которые обычно обслуживают запросы в однозначных (или двухзначных) миллисекундах, это проблематично. Как бы то ни было, это была практическая проблема с внутренним хранилищем, используемым службой Amazon Simple Queue (не могу вдаваться в подробности, поскольку это внутреннее хранилище AWS).
StaxMan
21
Раздражающий момент в GC заключается в том, что Azul изобрел много лет назад гениальный алгоритм GC (Azul C4), который может легко справиться с сотнями гигабайт без каких-либо заметных пауз за счет очень разумного использования аппаратного обеспечения памяти процессора. Но этого никто не знает, и в ближайшее время это не будет реализовано в основных версиях Java, поскольку требует некоторой поддержки со стороны операционной системы. И поставщики операционных систем ничего не сделают, пока люди не узнают об алгоритме и не окажут давление на поставщиков операционных систем. См. Azulsystems.com/zing/pgc , managedruntime.org
Hans-Peter Störr
58

Я тестировал это с тяжелым приложением: 60-70 ГБ выделено в куче, а 20-50 ГБ используются в любое время. С такими приложениями будет преуменьшением сказать, что ваш опыт может отличаться. Я использую JDK 1.6_22 в Linux. Важны второстепенные версии - примерно до 1.6_20 в G1 были ошибки, которые вызывали случайные исключения NullPointerExceptions.

Я обнаружил, что он очень хорошо удерживает цель паузы, которую вы ему задаете большую часть времени. По умолчанию, пауза составляет 100 мс (0,1 секунды), и я сказал ему сделать половину этого (-XX: MaxGCPauseMillis = 50). Однако, как только память становится действительно нехваткой, она паникует и выполняет полную сборку мусора. С 65 ГБ это занимает от 30 секунд до 2 минут. (Количество процессоров, вероятно, не имеет значения; оно, вероятно, ограничено скоростью шины.)

По сравнению с CMS (которая не является сервером GC по умолчанию, но должна быть для веб-серверов и других приложений реального времени), типичные паузы намного более предсказуемы и могут быть намного короче. Пока мне больше везет с CMS из-за огромных пауз, но это может быть случайным; Я вижу их всего несколько раз каждые 24 часа. Я не уверен, какой из них будет более подходящим для моей производственной среды на данный момент, но, вероятно, G1. Если Oracle продолжит настройку, я подозреваю, что G1 в конечном итоге станет явным победителем.

Если у вас нет проблем с существующими сборщиками мусора, нет причин рассматривать G1 прямо сейчас. Если вы запускаете приложение с низкой задержкой, такое как приложение с графическим интерфейсом, G1, вероятно, будет правильным выбором, так как MaxGCPauseMillis установлен на очень низком уровне. Если вы запускаете приложение в пакетном режиме, G1 вам ничего не покупает.

Дэвид Леппик
источник
14

Хотя я не тестировал G1 в производственной среде, я подумал, что прокомментирую, что сборщики мусора уже проблематичны для случаев без «огромных» куч. В частности, GC может серьезно повлиять на сервисы с, скажем, 2 или 4 гигабайтами. Сборщики мусора молодого поколения обычно не вызывают проблем, поскольку они заканчиваются за однозначные миллисекунды (или, самое большее, двузначные). Но коллекции старого поколения гораздо более проблематичны, так как они занимают несколько секунд при размерах старого поколения 1 гигабайт или выше.

Теперь: теоретически CMS может здесь очень помочь, так как она может выполнять большую часть своей работы одновременно. Однако со временем будут случаи, когда он не сможет этого сделать и будет вынужден вернуться к сбору «остановить мир». И когда это произойдет (скажем, через час - не часто, но все же слишком часто), ну, держитесь за свои гребаные шляпы. Это может занять минуту или больше. Это особенно проблематично для служб, которые пытаются ограничить максимальную задержку; вместо того, чтобы обрабатывать запрос, скажем, 25 миллисекунд, теперь он занимает десять секунд или больше. Чтобы добавить вреда к оскорблению, клиенты затем часто отключают запрос и повторяют попытку, что приводит к дальнейшим проблемам (так называемый «дерьмовый шторм»).

Это одна из областей, где G1 очень надеялся помочь. Я работал в большой компании, которая предлагает облачные сервисы для хранения и отправки сообщений; и мы не могли использовать CMS, поскольку, хотя большую часть времени она работала лучше, чем параллельные разновидности, у нее случались сбои. Так что около часа все было хорошо; а затем все поразило ... и поскольку обслуживание было основано на кластерах, когда один узел попадал в проблему, другие обычно следовали (поскольку таймауты, вызванные сборщиком мусора, приводят к тому, что другие узлы считают, что узел разбился, что привело к перенаправлению).

Я не думаю, что сборщик мусора представляет собой большую проблему для приложений, и, возможно, даже некластеризованные службы страдают реже. Но все больше и больше систем объединяются в кластеры (особенно благодаря хранилищам данных NoSQL), и размеры кучи растут. Сборщики мусора OldGen суперлинейно связаны с размером кучи (это означает, что удвоение размера кучи более чем удваивает время сборки мусора, при условии, что размер набора динамических данных также удваивается).

StaxMan
источник
13

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

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

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

И чтобы исправить заявление, сделанное в предыдущем ответе, Zing не требует никаких изменений в операционной системе. Он работает так же, как и любая другая JVM в неизмененных дистрибутивах Linux.

Скотт Селлерс
источник
3
Мне просто интересно, как Azul C4 достиг того, что вы сказали, и почему Sun или Oracle не могут. Есть какой-то большой секрет или это просто компромисс?
Джордж
5
Azul C4 имеет уникальную технологию, которая берет свое начало в аппаратных вычислительных устройствах Azul (которые используют специализированные процессоры, созданные для запуска корпоративных Java-приложений), и была разработана для работы на обычных серверах x86 под управлением Linux. Любой другой сборщик мусора корпоративного класса (будь то Oracle или IBM) в какой-то момент должен делать паузы остановки мира - уникальный атрибут Azul C4 заключается в том, что он никогда не делает этих проблемных пауз STW. Если вам интересно, изобретатели коллектора C4 опубликовали статью о том, как это работает: dl.acm.org/citation.cfm?id=1064988 .
Скотт Селлерс
Скотт, я прочитал здесь blog.mikemccandless.com/2012/07/…, что Azul поставляет модуль ядра, который предварительно выделяет память для использования JVM. Это не правда? Если это правда, это не большая модификация ядра, но все же модификация.
Дэн Притс
4
Джордж, два слова: патент защищен. Дэн, когда вы покупаете Zing, часть того, за что вы платите, заключается в том, чтобы их сотрудники службы поддержки настраивали его для вашего приложения - и это включает распределение общего использования системной памяти. Сам модуль ядра предотвращает запись в блок памяти, который собирается сборщиком мусора. Это секретный соус, который делает его «без пауз»: потоки приостанавливаются только в том случае, если они пытаются записать в один из этих блоков, и только на время, достаточное для сжатия этого блока.
Дэвид Леппик
13

Мы уже используем G1GC почти два года назад. Он отлично справляется с нашей системой обработки критически важных транзакций, и он оказался отличной поддержкой в ​​отношении высокой пропускной способности, низких пауз, параллелизма и оптимизированного управления тяжелой памятью.

Мы используем следующие настройки JVM:

-server -Xms512m -Xmx3076m -XX:NewRatio=50 -XX:+HeapDumpOnOutOfMemoryError -XX:+UseG1GC -XX:+AggressiveOpts -XX:+UnlockExperimentalVMOptions -XX:MaxGCPauseMillis=400 -XX:GCPauseIntervalMillis=8000 -XX:+PrintGCTimeStamps -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCApplicationConcurrentTime

Обновлено

-d64 -server -Xss4m -Xms1024m -Xmx4096m -XX:NewRatio=50 -XX:+UseG1GC -XX:+UnlockExperimentalVMOptions -XX:+HeapDumpOnOutOfMemoryError -XX:-DisableExplicitGC -XX:+AggressiveOpts -Xnoclassgc -XX:+UseNUMA -XX:+UseFastAccessorMethods -XX:ReservedCodeCacheSize=48m -XX:+UseStringCache -XX:+UseStringDeduplication -XX:MaxGCPauseMillis=400 -XX:GCPauseIntervalMillis=8000
Emkays
источник
5
В Java 8 вам не нужно устанавливать -XX: + UseCompressedOops или -XX: + DoEscapeAnalysis, будка включена по умолчанию. См .: docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html
Мирко Эберт,
8

Коллектор G1 снижает влияние полных коллекций. Если у вас есть приложение, в котором вы уже сократили потребность в полных коллекциях, сборщик Concurrent map Sweep так же хорош, и, по моему опыту, имеет более короткое время сбора второстепенных.

Питер Лоури
источник
«обратите внимание, что использование G1 в производственной среде разрешено только при приобретении контракта на поддержку Java.», groups.google.com/forum/#!topic/javaposse/Vm0a4H-QY54 , так что это миф или нет?
Christophe Roussy
1
@ChristopheRoussy Я не знаю, правда ли это больше (или есть доказательства, что это когда-либо было правдой). Это не требует -XX: + UnlockCommercialFeatures, поэтому я подозреваю, что G1 не требует лицензии.
Питер Лоури
5

Похоже, что G1, запускающий JDK7u4, наконец-то официально поддерживается, см. RN для JDK7u4 http://www.oracle.com/technetwork/java/javase/7u4-relnotes-1575007.html .

Судя по нашему тестированию для больших JVM, настроенная CMS по-прежнему работает лучше, чем G1, но я думаю, она станет лучше.

Bubi S
источник
5

Недавно меня переехали из

CMS в G1GC с кучей 4G и 8-ядерным процессором на серверах с JDK 1.7.45 .

(JDK 1.8.x G1GC предпочтительнее 1.7, но из-за некоторых ограничений я должен придерживаться версии 1.7.45)

Я настроил следующие ключевые параметры и сохранил все остальные параметры по умолчанию.

-XX:G1HeapRegionSize=n, XX:MaxGCPauseMillis=m, -XX:ParallelGCThreads=n, 
-XX:ConcGCThreads=n apart from -Xms and -Xmx

Если вы хотите точно настроить эти параметры, прочтите эту статью о Oracle .

Основные наблюдения:

  1. Использование памяти соответствует G1GC, в отличие от высоких и низких значений в CMS
  2. Максимальное время паузы GC меньше по сравнению с CMS
  3. Время, затрачиваемое на сборку мусора, в G1GC немного выше, чем в CMS.
  4. Количество крупных коллекций практически ничтожно по сравнению с CMS
  5. Количество второстепенных коллекций выше по сравнению с CMS

Но все же я рад, что максимальное время паузы GC меньше, чем у CMS. Я установил максимальное время паузы сборщика мусора как 1,5 секунды, и это значение еще не превышено.

Связанный вопрос SE:

Сборка мусора Java 7 (JDK 7) и документация по G1

Равиндра бабу
источник
4

CMS может привести к медленному снижению производительности, даже если вы запускаете его без накопления зарезервированных объектов. Это происходит из-за фрагментации памяти, которую G1 якобы избегает.

Миф о том, что G1 доступен только при платной поддержке, - это всего лишь миф. Sun и теперь Oracle разъяснили это на странице JDK.

Тед Даннинг
источник
4

G1 GC должен работать лучше. Но если установить -XX: MaxGCPauseMillis слишком агрессивно, мусор будет собираться слишком медленно. Вот почему в примере Дэвида Леппика сработал полный сборщик мусора.

дефис
источник
4

Я только что реализовал сборщик мусора G1 в нашем проекте Terracotta Big Memory. При работе с разными типами коллекторов G1 дал нам лучшие результаты с временем отклика менее 600 мс.

Вы можете найти результаты тестов (всего 26) здесь

Надеюсь, это поможет.

Спанглиш
источник
3

Недавно я перенес часть Twicsy на новый сервер с 128 ГБ ОЗУ и решил использовать версию 1.7. Я начал использовать все те же настройки памяти, что и с 1.6 (у меня есть несколько экземпляров, выполняющих разные вещи, от 500 МБ кучи до 15 ГБ, а теперь новый с 40 ГБ), и это вообще не сработало. . 1.7, похоже, использует больше кучи, чем 1.6, и в первые несколько дней у меня было много проблем. К счастью, у меня было много оперативной памяти для работы, и я увеличил объем оперативной памяти для большинства моих процессов, но все еще имел некоторые проблемы. Моим обычным MO было использовать очень маленький минимальный размер кучи 16 м, даже с максимальной кучей в несколько гигабайт, а затем включить инкрементный сборщик мусора. Это сводило паузы к минимуму. Однако сейчас это не работает, и мне пришлось увеличить минимальный размер примерно до того, что я ожидал использовать в среднем в куче, и это сработало очень хорошо. У меня все еще включен инкрементный сборщик мусора, но я попробую и без него. Теперь никаких пауз, и кажется, что все идет очень быстро. Итак, я думаю, что мораль этой истории в том, что не ожидайте, что ваши настройки памяти будут идеально переведены с 1,6 на 1,7.

Крис Селин
источник
2

G1 делает приложение намного более гибким: увеличивается его латантность - приложение можно назвать «мягким в реальном времени». Это достигается заменой двух типов запусков сборщика мусора (маленьких второстепенных и одного большого на Tenured Gen) на малые равные по размеру.

Подробнее см. Здесь: http://geekroom.de/java/java-expertise-g1-fur-java-7/

Даниэль
источник
1

Я работаю с Java для маленькой и большой кучи, и вопрос о GC и Full GC появляется каждый день, так как ограничения могут быть более строгими, чем другие: в определенной среде 0,1 секунды мусорщика GC или Full GC, kill просто fonctionnalité, иметь детальную конфигурацию и возможности (CMS, iCMS, другие ... цель здесь, чтобы иметь наилучшее возможное время отклика с обработкой почти в реальном времени (здесь обработка в реальном времени часто составляет 25 мс) Итак, в принципе, любые улучшения в эргономике и эвристике ГХ приветствуются!

Фуби
источник
1

Я использую G1GC на Java 8, а также с Groovy (также Java 8), и я выполняю различные виды рабочих нагрузок, и в целом G1GC работает следующим образом:

  • Использование памяти очень низкое, например, 100 МБ вместо 500 МБ по сравнению с настройками Java по умолчанию.

  • Время отклика стабильное и очень низкое

  • Производительность между настройками по умолчанию и G1GC составляет 20% замедления при использовании G1GC в худшем случае (без настройки, однопоточное приложение). Это не так много, учитывая хорошее время отклика и низкое использование памяти.

  • При запуске из Tomcat, который является многопоточным, общая производительность на 30% выше, а использование памяти намного ниже, а время отклика намного меньше.

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

Андрей
источник
0

Не рекомендуется использовать java8 с G1GC для вычисления с плавающей точкой с JVM, подобной хот-споту. Это опасно для целостности и точности приложения.

https://bugs.openjdk.java.net/browse/JDK-8148175

JDK-8165766

JDK-8186112

user7796409
источник