#java #algorithm #garbage-collection
#java #алгоритм #сбор мусора
Вопрос:
Я пытаюсь глубже понять сбор мусора Java.
В коллекции поколений HotSpot JVM в куче есть три области (молодое поколение, старое поколение и постоянное поколение). Кроме того, существует два вида алгоритмов:
1) Отметьте Sweep Compact.
2) Одновременная пометка и зачистка.
Верно ли, что необходимость GC в «Остановке мира» зависит от используемого алгоритма, а не от того, с каким поколением он работает? Другими словами, если я использую 1) в качестве алгоритма GC во всех трех областях, STW всегда будет происходить?
Кроме того, я понимаю, что разница в том, что второй алгоритм GC не требует уплотнения, что в конечном итоге приведет к фрагментации. Итак, второй вопрос заключается в том, почему для уплотнения требуется пауза STW?
Ответ №1:
Основная причина, по которой сжатие приводит к паузе STW, заключается в следующем, JVM необходимо переместить объект и обновить ссылки на него. теперь, если вы переместите объект перед обновлением ссылок и запущенное приложение получит к нему доступ по старой ссылке, возникнут проблемы. если вы сначала обновите ссылку, а затем попытаетесь переместить объект, обновленная ссылка будет неверной до тех пор, пока объект не будет перемещен, и любой доступ, пока объект не был перемещен, вызовет проблему.
Как для CMS, так и для Parallel collecter алгоритм сбора молодого поколения схож, и он заключается в остановке мира, т.е. приложение останавливается, когда происходит сбор, что делает JVM, помечая все объекты, доступные из корневого набора, перемещая объекты из Eden в survivor space и перемещая объекты, которые сохранили коллекции, превышающие пороговое значение для старого поколения. Конечно, JVM должна обновить все ссылки на перемещенные объекты.
Для старого поколения parallel collector выполняет всю разметку, уплотнение и обновление ссылок за одну фазу остановки мира (STW), это приводит к секундным паузам для куч в GBS. Это было болезненно для приложений, которые предъявляют строгие требования ко времени отклика. На сегодняшний день Paralle collector по-прежнему является лучшим сборщиком (среди Oracle Java) по пропускной способности или пакетной обработке. Фактически, мы видели для того же сценария, даже если время, проведенное в паузах, больше в параллельном сборщике, чем в CMS, мы все равно получаем более высокую пропускную способность, я думаю, это связано с лучшей пространственной локализацией из-за уплотнения.
CMS решила проблему больших пауз в основной коллекции, выполнив разметку одновременно. Есть 2 части STW, начальная разметка (получение ссылок из корневого набора) и пауза с замечаниями (небольшая пауза STW в конце разметки для обработки изменений в графе объектов во время разметки и одновременной работы приложения). Обе эти паузы находятся в диапазоне 100-200 миллисекунд при размерах кучи в несколько ГБ и разумном количестве потоков приложения (помните, что чем больше активных потоков, тем больше корней)
Планируется, что G1GC станет заменой CMS и будет принимать цели для пауз. заботится о фрагментации путем постепенного уплотнения кучи.Хотя работа выполняется постепенно, поэтому вы можете получать меньшие паузы, но это может происходить за счет более частых пауз
Ничто из вышеперечисленного не может уплотнять кучу (CMS вообще не уплотняет) во время работы приложения. Сборщик мусора AZUL GPGC может даже уплотняться без остановки приложения, а также обрабатывать обновление ссылки. Итак, если вы хотите углубиться в то, как работают GCS, стоит прочитать алгоритм для GPGC. AZUL позиционирует его как сборщик без пауз.
Комментарии:
1. Фантастическое резюме часто сбивающей с толку сложности, связанной с GCs, я не думаю, что я читал такое аккуратное, краткое описание GCs раньше. Нужно добавить еще один GC — это Shenandoah , который создан для Java 9, но есть бэкпорт для Java 8. Пропускная способность не такая хорошая, как у G1, но если ваша цель — сверхнизкая пауза, это расширяет границы. rkennke.wordpress.com/2016/02/08/shenandoah-performance
2. @michaelok начало этого ответа просто неверно. Перемещение объекта и обновление ссылки могут (и выполняются) выполняться одновременно,
Shenandoah 2.0
например. Так что да, причины STW разные
Ответ №2:
Во всех свободно доступных GCS в openjdk есть некоторые, которые останавливают мировые события. И не только GCS, другие вещи, такие как деоптимизация, также могут запускать безопасные точки.
Но не все паузы равны. CMS и G1 не нужно масштабировать время паузы в соответствии с набором данных в реальном времени в старом поколении, потому что они сканируют только подмножество объектов во время пауз и выполняют основную часть своей работы одновременно, в отличие от последовательных сборщиков и сборщиков пропускной способности.
ZGC (доступен с OpenJDK11) и Shenandoah (с 12) являются сборщиками, которые дополнительно отделяют время паузы от размера набора данных в реальном времени и масштабируют свои паузы только с размером корневого набора вместо этого.
Кроме того, существуют другие реализации GC, которые избегают глобальных пауз — в них все еще могут возникать паузы для каждого потока — или делают длительность паузы O (1), т. е. независимой от размера текущего набора данных. Часто цитируемый пример — C4 collector от azul.
Итак, второй вопрос заключается в том, почему сжатию требуется пауза STW?
Уплотнение означает перемещение объектов. Перемещение объектов означает, что указатели необходимо обновлять. Этого очень сложно или дорого достичь безопасно, когда потоки приложений все еще выполняются.
Параллельные алгоритмы обычно платят некоторую стоимость за пропускную способность и сложность в обмен на меньшее время паузы. Отсутствие компактирования делает CMS относительно (!) простой для параллельного сборщика.
Комментарии:
1. Вы упоминаете
ZGC
иShenandoah
и движущиеся объекты и указатели в качестве причины STW, но они оба перемещают объекты одновременно. Может быть, я пропустил -прочитал ваш ответ?2. @Eugene нет, я не писал, что движущиеся объекты являются причиной STW. На самом деле я даже не писал, что уплотнение должно быть STW. Просто то, что это трудно выполнять одновременно с потоками приложения. И эти утверждения содержатся в разных параграфах, которые не ссылаются друг на друга. Итак, я никоим образом не имел в виду, что ZGC или shenandoah нуждаются в STW для уплотнения.
Ответ №3:
Вот ссылка, которая дает некоторую полезную информацию о различных сборщиках в java 8:https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/collectors.html#sthref27
Все стратегии приведут к остановке мира. Но ваши требования к производительности могут подтолкнуть вас к выбору различных стратегий GC для повышения производительности или времени отклика.
Ответ №4:
Остановка мира произойдет независимо от того, какой алгоритм GC вы выберете. Остановка мира означает, что JVM останавливает запуск приложения для выполнения GC. Когда происходит остановка мира, каждый поток, за исключением потоков, необходимых для GC, останавливает свои задачи.
Комментарии:
1. Вы знаете, что существуют инкрементные и параллельные алгоритмы сбора мусора.
2. Да , Инкрементный GC также останавливает потоки приложения . Пожалуйста, взгляните oracle.com/technetwork/java/javase/gc-tuning-6-140523.html#icms
3. У Azul Systems есть алгоритм GC для своей виртуальной машины Zing, который не использует stop the world, но я думаю, что в OP говорилось о виртуальной машине Oracle, и они возвращаются к STW, хотя, конечно, алгоритмы GC развивались годами и продолжают совершенствоваться, взгляните на Shenandoah «Shenandoah — это сборщик мусора со сверхнизким временем паузы, который сокращает время паузы GC, выполняя больше работы по сбору мусора одновременно с запущенной программой Java. » openjdk.java.net/projects/shenandoah