#common #java (сам офигел)
G1GC 1/2.
Я обещал рассказать про сборщики мусора в разных языках программирования, но как-то так вышло, что всё, что хочется вкинуть слишком много для одного раза, так что буду делиться частями, чтобы и вы не померли читать, и я не загнулся писать книжки вместо постов (даже Пиши сокращай не помогает).
Внутри Hotspot JVM (я так понял в мире жавы существует много разных vm прям как компиляторов в плюсах или интерпретаторов в питоне, но это каноничный от Sun microsystems и соответственно Oracle) есть несколько дефолтных сборщиков мусора. Сегодня по ним и пройдёмся.
SerialGC -- последовательный сборщик мусора, состоящий из DefNEW и Tenured. Первый занимается сборкой молодого поколения и является копирующим сборщиком мусора, второй же следит за взрослым поколением и является модифицированным алгоритмом mark-sweep-compact. В силу того, что на обоих этапах происходит перемещение, аллокация аналогично pooled-аллокаторам (выдали указатель, сдвинули cur в пуле).
ParallelGC (ParNEW) -- параллельный сборщик мусора, состоящий из параллельного копирующего для молодого поколения и параллельного mark-compact для взрослого поколения. Аллокация также линейная. Несмотря на параллельность, он всё ещё является stop-the-world, однако паузы в среднем меньше.
CMS -- параллельный сборщик мусора, пытающийся минимизировать паузы приложения и использовать фоновую сборку. При первой остановке приложения фиксируется граф объектов. Далее в фоновом режиме этот граф обходится. На следующей остановке учитываются изменения, которые могли произойти за время фонового обхода, после чего в фоне происходит sweep этап. Структурно используется параллельный копирующий сборщик для молодого поколения, а для взрослого поколения фоновый mark-sweep. Аллокация происходит из freelist'ов, что приводит к фрагментации. Компактификация происходит только в случае, когда памяти начинает не хватать, что приводит к полной сборке мусора (для CMS это полный stop-the-world в один поток🤢). В последних версиях джавы был удалён, т.к. авторы перестали поддерживать.
Я так понял, что первые два есть просто по приколу, и можно юзать их, если вам прям ну не критично совсем, что там да как у вас работает или отдохнуть прилегло. CMS рекомендовался, если хочется паузы поменьше, но куча приложения не оч большая (до 2Гб).
G1GC 1/2.
Я обещал рассказать про сборщики мусора в разных языках программирования, но как-то так вышло, что всё, что хочется вкинуть слишком много для одного раза, так что буду делиться частями, чтобы и вы не померли читать, и я не загнулся писать книжки вместо постов (даже Пиши сокращай не помогает).
Внутри Hotspot JVM (я так понял в мире жавы существует много разных vm прям как компиляторов в плюсах или интерпретаторов в питоне, но это каноничный от Sun microsystems и соответственно Oracle) есть несколько дефолтных сборщиков мусора. Сегодня по ним и пройдёмся.
SerialGC -- последовательный сборщик мусора, состоящий из DefNEW и Tenured. Первый занимается сборкой молодого поколения и является копирующим сборщиком мусора, второй же следит за взрослым поколением и является модифицированным алгоритмом mark-sweep-compact. В силу того, что на обоих этапах происходит перемещение, аллокация аналогично pooled-аллокаторам (выдали указатель, сдвинули cur в пуле).
ParallelGC (ParNEW) -- параллельный сборщик мусора, состоящий из параллельного копирующего для молодого поколения и параллельного mark-compact для взрослого поколения. Аллокация также линейная. Несмотря на параллельность, он всё ещё является stop-the-world, однако паузы в среднем меньше.
CMS -- параллельный сборщик мусора, пытающийся минимизировать паузы приложения и использовать фоновую сборку. При первой остановке приложения фиксируется граф объектов. Далее в фоновом режиме этот граф обходится. На следующей остановке учитываются изменения, которые могли произойти за время фонового обхода, после чего в фоне происходит sweep этап. Структурно используется параллельный копирующий сборщик для молодого поколения, а для взрослого поколения фоновый mark-sweep. Аллокация происходит из freelist'ов, что приводит к фрагментации. Компактификация происходит только в случае, когда памяти начинает не хватать, что приводит к полной сборке мусора (для CMS это полный stop-the-world в один поток🤢). В последних версиях джавы был удалён, т.к. авторы перестали поддерживать.
Я так понял, что первые два есть просто по приколу, и можно юзать их, если вам прям ну не критично совсем, что там да как у вас работает или отдохнуть прилегло. CMS рекомендовался, если хочется паузы поменьше, но куча приложения не оч большая (до 2Гб).
👍3❤1
#common #java
G1GC 2/2.
G1 (garbage-first/G one) является сборщиком мусора общего назначения (i.e. работает со всей кучей). Он является параллельным фоновым сборщиком мусора, который пытается минимизировать паузы приложения. Основной абстракцией является сборка поколениями: существует молодое и взрослое поколение. Молодое поколение содержит три пула: основной (eden) и два дополнительных (survivors). Основной пулл содержит самые молодые объекты, два дополнительных используются для копирующей сборки мусора внутри молодого поколения (то есть внутри молодого поколения существует разделение на подпоколения: прям ну совсем молодые чуваки и объекты, пережившие хотя бы одну сборку). Когда в молодом поколении недостаточно места для новой аллокации, происходит малая сборка мусора. Она заключается в том, что все выжившие в eden объекты перемещаются в один из пулов для копирующей сборки.
Элементы из копирующего сборщика могут быть либо удалены, либо перемещены внутри копирующего сборщика, либо перенесены во взрослое поколение (если сборщик мусора примет такое решение).
Вся куча приложения делится на регионы размером от 1Мб до 32Мб. Каждый регион динамически относится в молодое/взрослое поколение (после сборок мусора регионы могут возвращаться во множество свободных и получать новую роль по необходимости).
В случае молодого регион может выполнять роль eden или survivor.
Особенная роль отводится большим объектам, которые не могут поместиться в один регион. Для них выделяется несколько рядом лежащих регионов. В процессе сборки мусора для таких объектов применяется отдельная логика (правда не обнаружил, какая именно, но вроде как там чуваки борются за дефрагментацию).
Во время сборки мусора выбирается множество регионов, которые будут очищаться (collection set). В него входят все регионы из молодого поколения и возможно некоторые из взрослого поколения (тут есть разделение по типу collection set'а: сборка только в молодых регионах, смешанная сборка и FullGC). Недостижимые объекты удаляются, а достижимые перемещаются в свободные регионы, которые назначаются либо регионами для взрослого поколения, либо survivor-регионами. При хорошем выборе регионов для очистки и засчёт compact новые регионы занимают меньше места, чем занимали объекты ранее (но не обязательно).
Для того, чтобы понимать, какие регионы из взрослого поколения стоит брать в очередной collection set, у каждого региона имеется remembered set, хранящий взаимосвязи объектов между регионами. То есть если объект из региона A ссылается на объект из региона B, то в rset'е B будет запись A. На основе этого ребята делают какие-то выводы.
Все этапы это stop-the-world, но есть этап фоновой маркировки, который стартует при достижении некоторого порога заполненности всей памяти приложения. Тут происходит несколько действий: обновляется информация о достижимости по регионам, освобождение регионов без живых объектов, устранение циклических зависимостей между неживыми объектами.
Когда хорошо юзать:
+ хотите паузы <0.5-1s;
+ минимальные настройки;
+ размер кучи >5Гб;
+ вам норм чиститься только когда больше половины кучи занято;
+ скорость создания объектов сильно меняется;
+ боремся с фрагментацией.
По настройкам кстати флагов у него хватает (кстати они оч забавные:
Вообще вся инфа из доклада одного из разрабов Oracle. Дока.
В планах ещё один java gc и бегло по другиим языкам, потому что пока чего-то крутого/подробного я в них не нашёл.
G1GC 2/2.
G1 (garbage-first/G one) является сборщиком мусора общего назначения (i.e. работает со всей кучей). Он является параллельным фоновым сборщиком мусора, который пытается минимизировать паузы приложения. Основной абстракцией является сборка поколениями: существует молодое и взрослое поколение. Молодое поколение содержит три пула: основной (eden) и два дополнительных (survivors). Основной пулл содержит самые молодые объекты, два дополнительных используются для копирующей сборки мусора внутри молодого поколения (то есть внутри молодого поколения существует разделение на подпоколения: прям ну совсем молодые чуваки и объекты, пережившие хотя бы одну сборку). Когда в молодом поколении недостаточно места для новой аллокации, происходит малая сборка мусора. Она заключается в том, что все выжившие в eden объекты перемещаются в один из пулов для копирующей сборки.
Элементы из копирующего сборщика могут быть либо удалены, либо перемещены внутри копирующего сборщика, либо перенесены во взрослое поколение (если сборщик мусора примет такое решение).
Вся куча приложения делится на регионы размером от 1Мб до 32Мб. Каждый регион динамически относится в молодое/взрослое поколение (после сборок мусора регионы могут возвращаться во множество свободных и получать новую роль по необходимости).
В случае молодого регион может выполнять роль eden или survivor.
Особенная роль отводится большим объектам, которые не могут поместиться в один регион. Для них выделяется несколько рядом лежащих регионов. В процессе сборки мусора для таких объектов применяется отдельная логика (правда не обнаружил, какая именно, но вроде как там чуваки борются за дефрагментацию).
Во время сборки мусора выбирается множество регионов, которые будут очищаться (collection set). В него входят все регионы из молодого поколения и возможно некоторые из взрослого поколения (тут есть разделение по типу collection set'а: сборка только в молодых регионах, смешанная сборка и FullGC). Недостижимые объекты удаляются, а достижимые перемещаются в свободные регионы, которые назначаются либо регионами для взрослого поколения, либо survivor-регионами. При хорошем выборе регионов для очистки и засчёт compact новые регионы занимают меньше места, чем занимали объекты ранее (но не обязательно).
Для того, чтобы понимать, какие регионы из взрослого поколения стоит брать в очередной collection set, у каждого региона имеется remembered set, хранящий взаимосвязи объектов между регионами. То есть если объект из региона A ссылается на объект из региона B, то в rset'е B будет запись A. На основе этого ребята делают какие-то выводы.
Все этапы это stop-the-world, но есть этап фоновой маркировки, который стартует при достижении некоторого порога заполненности всей памяти приложения. Тут происходит несколько действий: обновляется информация о достижимости по регионам, освобождение регионов без живых объектов, устранение циклических зависимостей между неживыми объектами.
Когда хорошо юзать:
+ хотите паузы <0.5-1s;
+ минимальные настройки;
+ размер кучи >5Гб;
+ вам норм чиститься только когда больше половины кучи занято;
+ скорость создания объектов сильно меняется;
+ боремся с фрагментацией.
По настройкам кстати флагов у него хватает (кстати они оч забавные:
-XX:MaxGCPauseMillis). Можно не пытаться подбирать такие конфигурации размеров регионов, что время пауз станет нормальным, а указать само время, и gc сам попытается подстроиться (не обещает, но постарается).Вообще вся инфа из доклада одного из разрабов Oracle. Дока.
В планах ещё один java gc и бегло по другиим языкам, потому что пока чего-то крутого/подробного я в них не нашёл.
❤1
#common #java
Java GC 1/2.
Из популярного в java ещё есть сборщик мусора Shenandoah. Как и G1, шенонда -- region based concurrent сборщик мусора.
Сначала происходит параллельная маркировка с двумя паузами до/после. В результате для каждого занятого региона становится понятно, как много живых объектов в нём содержится. Из регионов с небольшим количеством достижимых объектов формируется collection set, из которого происходит фоновое уплотнение в новый регион (concurrent evacuation).
После уплотнения нельзя считать, что регионы, из которых происходило уплотнение, можно ощищать.
На данные в них могут существовать ссылки из других регионов, потому следующим этапом производится перезапись ссылок с данных из старых регионов на данные в уплотнённом (concurrent update refs; тоже паузы до/после). После этого можно считать регионы очищенными и аллоцировать из них память.
Java GC 1/2.
Из популярного в java ещё есть сборщик мусора Shenandoah. Как и G1, шенонда -- region based concurrent сборщик мусора.
Сначала происходит параллельная маркировка с двумя паузами до/после. В результате для каждого занятого региона становится понятно, как много живых объектов в нём содержится. Из регионов с небольшим количеством достижимых объектов формируется collection set, из которого происходит фоновое уплотнение в новый регион (concurrent evacuation).
После уплотнения нельзя считать, что регионы, из которых происходило уплотнение, можно ощищать.
На данные в них могут существовать ссылки из других регионов, потому следующим этапом производится перезапись ссылок с данных из старых регионов на данные в уплотнённом (concurrent update refs; тоже паузы до/после). После этого можно считать регионы очищенными и аллоцировать из них память.
❤1
#common #java
Java GC 2/2.
Ещё одним известным сборщиком мусора в Java является ZGC. По принципу действия он аналогичен Shenandoah с точностью до некоторых локальных оптимизаций, которые, тем не менее, иногда играют значительную роль в использовании. Важным достижением ZGC являются константные stop-the-world паузы.
А ещё есть no-op EpsilonGC.
Вообще весь движ начинается в момент реализации барьеров на чтение/запись. Там какие-то java-специфичные вещи довольно. Если интересно, можно посмотреть докладик Алексея Шипилёва (я так понял, это Полухин из мира жавы).
На картиночке условное сравнение, чтобы выбрать gc по нуждам.
[1]. Shenandoah 1.
[2]. Shenandoah 2.
P.S. На правах рекламы вкину статью про обучение очень больших моделек. Что делать, если они не помещаются на GPU, и как с этим вообще жить: link. Вдруг тут есть любители машинок : )
Java GC 2/2.
Ещё одним известным сборщиком мусора в Java является ZGC. По принципу действия он аналогичен Shenandoah с точностью до некоторых локальных оптимизаций, которые, тем не менее, иногда играют значительную роль в использовании. Важным достижением ZGC являются константные stop-the-world паузы.
А ещё есть no-op EpsilonGC.
Вообще весь движ начинается в момент реализации барьеров на чтение/запись. Там какие-то java-специфичные вещи довольно. Если интересно, можно посмотреть докладик Алексея Шипилёва (я так понял, это Полухин из мира жавы).
На картиночке условное сравнение, чтобы выбрать gc по нуждам.
[1]. Shenandoah 1.
[2]. Shenandoah 2.
P.S. На правах рекламы вкину статью про обучение очень больших моделек. Что делать, если они не помещаются на GPU, и как с этим вообще жить: link. Вдруг тут есть любители машинок : )
👍3❤1