Что такое сборщик мусора

Современный подход к сборке мусора

Что такое сборщик мусора. Смотреть фото Что такое сборщик мусора. Смотреть картинку Что такое сборщик мусора. Картинка про Что такое сборщик мусора. Фото Что такое сборщик мусора

В последнее время мне встречалось немало статей, в которых не самым удачным для меня образом продвигается свежий сборщик мусора в Go. Некоторые из статей написали разработчики самого языка, и их утверждения намекали на радикальный прорыв в технологии сборки мусора.

Вот первичный анонс о внедрении нового сборщика, датированный августом 2015-го:

В Go создаётся сборщик мусора (GC) не только для 2015 года, но и для 2025-го, и ещё дальше… Сборщик в Go 1.5 возвещает о наступлении будущего, в котором паузы на сборку больше не являются барьером для перехода на безопасный язык. Это будущее, в котором приложения без труда масштабируются вместе с оборудованием, и по мере роста мощности оборудования сборщик мусора больше не является сдерживающим фактором при создании более качественного, масштабируемого ПО. Go — хороший язык для использования как минимум в ближайший десяток лет.

Создатели утверждают, что они не просто решили проблему пауз на сборку мусора, а пошли куда дальше:

Одним из высокоуровневых способов решения проблем с производительностью является добавление GC-настроек (knobs), по одной на каждую проблему. Программист может менять их, подбирая наилучшую комбинацию для своего приложения. Недостатком этого подхода является то, что при внедрении каждый год одной-двух новых настроек через десять лет придётся законодательно регулировать труд людей, которые будут менять эти настройки. Go не пошёл по этому пути. Вместо кучи настроек мы оставили одну и назвали её GOGC.

Более того, освободившись от бремени поддержки десятков настроек, разработчики могут сосредоточиться на улучшении runtime’а приложения.

Не сомневаюсь, что многие пользователи Go были просто счастливы получить новый подход к runtime’у в Go. Но у меня есть претензии к этим заявлениям: они выглядят как недостоверный маркетинговый булшит. А поскольку они раз за разом воспроизводятся в Сети, пришло время подробно с ними разобраться.

Реальность такова, что в сборщике мусора в Go не реализовано никаких новых идей или результатов исследований. Как признаются сами авторы, это просто сборщик с параллельной пометкой и очисткой, основанный на идеях 1970-х. Это примечательно лишь потому, что сборщик был разработан для оптимизации продолжительности пауз за счёт всех остальных важных характеристик сборщика. В технических и маркетинговых материалах Go не упоминается обо всех этих побочных эффектах, поэтому многие программисты не подозревают об их существовании. В результате создаётся впечатление, что конкурентные языки — плохо спроектированный шлак. И авторы Go лишь подогревают эти мысли:

Для создания сборщика на следующее десятилетие мы обратились к алгоритмам из десятилетий прошлых. В нашем сборщике реализован трёхцветный (tri-color) алгоритм параллельной пометки и очистки, предложенный Dijkstra в 1978 году. Это намеренное отличие от большинства современных сборщиков «корпоративного» класса, которое, как мы считаем, лучше всего соответствует особенностям современного оборудования и требованиям по уровню задержки в современном ПО.

Читаешь всё это, и возникает мысль, что за последние 40 лет в сфере «корпоративных» сборщиков мусора ничего лучше предложено не было.

Введение в теорию сборки мусора

При разработке алгоритма сборки мусора нужно учитывать ряд факторов:

Из-за сложности пространства проектных параметров сборка мусора представляет собой подобласть информатики, богато освещённую в исследовательских работах. Новые алгоритмы предлагаются и внедряются регулярно, как в академической, так и в коммерческой среде. Но, к сожалению, никто ещё не создал алгоритма, подходящего для всех случаев жизни.

Кругом сплошные компромиссы

Разберёмся с этим подробнее.

Первые алгоритмы сборки мусора разработали для однопроцессорных компьютеров и программ с маленькими кучами. Ресурсы процессора и памяти были дороги, а пользователи — нетребовательны, так что к паузам в работе программ относились лояльно. Создававшиеся в те времена алгоритмы старались поменьше задействовать процессор и минимизировать избыточное потребление памяти в куче. Это означало, что сборщик ничего не делал до тех пор, пока программа могла размещать в памяти данные. Затем она вставала на паузу до полного выполнения пометки и очистки кучи, чтобы как можно скорее освободить часть памяти.

У старых сборщиков есть преимущества: они просты; не замедляют программу, если не выполняют свою работу; не приводят к избыточному потреблению памяти. Консервативные сборщики, например Boehm GC, даже не требуют вносить изменения в компилятор или язык программирования! Это делает их подходящими для настольных приложений (обычно их кучи маленького размера), в том числе для видеоигр категории ААА; в них большая часть памяти занята файлами с данными, которые не нужно сканировать.

Алгоритмы, для которых характерны паузы полной остановки (Stop-the-world, STW) для выполнения пометки и очистки, чаще всего изучают на курсах по информатике. Иногда на собеседованиях я прошу кандидатов немного рассказать о сборке мусора. И чаще всего они представляют сборщик как чёрную коробку, внутри которой неизвестно что происходит, либо считают, что в нём используется очень старая технология.

Проблема в том, что такие простые паузы на пометку и очистку крайне плохо масштабируются. Если добавить ядра и увеличить соотношения объёмов куч и размещений в памяти, то алгоритм перестаёт хорошо работать. Но иногда, когда применяются маленькие кучи, даже простые алгоритмы вполне сносно выполняют свою задачу! В подобных ситуациях вы можете воспользоваться подобным сборщиком и минимизировать избыточность потребления памяти.

Другая крайность — использование куч размером в сотни гигабайтов на машинах с десятками ядер. Например, на серверах, обслуживающих биржевые транзакции или поисковые запросы. В подобных ситуациях нужно сделать паузы как можно короче. И тогда предпочтительнее могут быть алгоритмы, в целом замедляющие работу программ за счёт фонового сбора мусора, но зато с очень короткими паузами.

На мощных системах вы также можете выполнять большие пакетные задания. Для них важны не паузы, а только общее время выполнения. В таких случаях лучше использовать алгоритм, который максимизирует пропускную способность (throughput), то есть отношение выполненной полезной работы ко времени, потраченному на сборку мусора.

Увы, нет ни одного алгоритма, полностью идеального. Также runtime ни одного языка не может определить, является ли ваша программа пакетным заданием или интерактивной программой, чувствительной к задержкам. Именно это, а не глупость разработчиков runtime’а, привело к появлению «настроек сборщика мусора». Это следствие фундаментальных ограничений информатики.

Гипотеза поколений (generational hypothesis)

В 1984 году было подмечено, что большинство размещений в памяти «умирают молодыми», то есть становятся мусором через очень короткое время после размещения. Это наблюдение, названное гипотезой поколений, — одно из сильнейших эмпирических наблюдений в сфере разработки языков программирования. Гипотеза вот уже несколько десятилетий подтверждается для самых разных языков: функциональных, императивных, не имеющих и имеющих типы данных.

Гипотеза поколений принесла пользу в том смысле, что алгоритмы сборки мусора стали использовать её плюсы. Так появились сборщики на основе поколений (generational collectors), которые имели ряд преимуществ по сравнению со старыми алгоритмами «остановить — пометить — очистить»:

Параллельный сборщик в Go

По факту программы на Go обычно требуют наличия обработчиков запросов/откликов вроде HTTP-серверов. То есть они демонстрируют поведение, сильно завязанное на поколениях. Создатели Go думают, как это можно использовать в будущем с помощью таких вещей, как «сборщик, ориентирующийся на запросы» (request oriented collector). Как уже заметили, это просто переименованный сборщик на основе поколений с настроенной политикой срока владения.
Можно эмулировать такой сборщик в других runtime’ах для обработчиков запросов/откликов. Для этого нужно удостовериться, что молодое поколение достаточно велико, чтобы в него поместился весь мусор, генерируемый при обработке запроса.

Но несмотря на это, используемый сегодня в Go сборщик — это не сборщик на основе поколений. Он просто выполняет в фоне старую добрую процедуру пометки с очисткой.

У такого подхода есть одно преимущество: можно получить очень-очень короткие паузы. Но все остальные параметры ухудшатся. Например:

Сервис 1 размещает больше памяти, чем Сервис 2, поэтому паузы полной остановки у него длиннее. Однако у обоих сервисов абсолютная продолжительность пауз остановки уменьшается на порядок. После включения на обоих сервисах мы наблюдали

20%-й рост потребления сборщиком времени процессора.

В данном случае продолжительность пауз в Go снизилась на порядок, но за счёт замедления работы сборщика. Можно ли это счесть оправданным компромиссом или длительность пауз и так уже была достаточно низкой? Автор не сказал.

Однако наступает момент, когда больше не имеет смысла наращивать возможности железа для сокращения пауз. Если паузы на сервере снизятся с 10 до 1 мс, заметят ли это пользователи? А если для такого снижения вам потребуется увеличить аппаратные ресурсы вдвое?

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

Сравнение с Java

Виртуальная машина Java HotSpot имеет несколько алгоритмов сборки мусора. Вы можете выбирать их через командную строку. Ни один из них не старается так сильно снизить продолжительность пауз, как Go, потому что они пытаются поддерживать баланс. Чтобы прочувствовать влияние компромиссов, можно сравнить алгоритмы друг с другом, переключаясь между разными сборщиками. Как? С помощью простого перезапуска программы, потому что компилирование выполняется по мере её исполнения, так что разные барьеры, необходимые для разных алгоритмов, могут по мере необходимости компилироваться и оптимизироваться в коде.

На современных компьютерах по умолчанию используется сборщик на основе поколений. Он создан для пакетных задач и изначально не обращает внимания на длительность паузы (её можно задавать в командной строке). Из-за возможности выбирать сборщик по умолчанию многие считают, что в Java паршивый сборщик мусора: из коробки Java пытается сделать так, чтобы ваше приложение работало как можно быстрее, с наименьшей избыточностью памяти, а на паузы наплевать.

Если вам нужно уменьшить продолжительность пауз, то можете переключиться на сборщик с параллельной пометкой и очисткой (concurrent mark/sweep collector, CMS). Это самое близкое к тому, что используется в Go. Но это алгоритм на основе поколений, поэтому паузы у него длиннее, чем в Go: молодое поколение уплотняется во время пауз, потому что выполняется перемещение объектов. В CMS есть два типа пауз: покороче, около 2—5 мс, и подлиннее, около 20 мс. CMS работает адаптивно: поскольку он выполняется одновременно (concurrent), то должен предполагать, когда ему запуститься (как и в Go). В то время как Go попросит вас сконфигурировать избыточность кучи, CMS самостоятельно адаптируется в ходе runtime, стараясь избежать сбоев режима одновременного выполнения. Поскольку большая часть кучи обрабатывается с помощью обычной пометки и очистки, то можно столкнуться с проблемами и тормозами из-за фрагментации кучи.

Самое свежее поколение сборщика в Java называется G1 (от garbage first). По умолчанию он работает начиная с Java 9. Авторы постарались сделать его как можно более универсальным. По большей части он выполняется одновременно, основан на поколениях (generational) и уплотняет всю кучу. Во многом самонастраиваемый. Но поскольку он не знает, чего вы хотите (как и все сборщики мусора), то позволяет регулировать компромиссы: просто укажите максимальный объём памяти, который вы ему выделяете, и размер пауз в миллисекундах, а всё остальное алгоритм подгонит самостоятельно, чтобы соблюсти ваши требования. По умолчанию длительность пауз около 100 мс, так что, если вы не уменьшите их самостоятельно, не ждите, что это сделает алгоритм: G1 отдаст предпочтение скорости работы приложения.

Паузы не совсем консистентны: большинство очень коротки (менее 1 мс), но есть и несколько длинных (более 50 мс), связанных с уплотнением кучи. G1 прекрасно масштабируется. Известны отзывы людей, которые применяли его на кучах терабайтного размера. Также у G1 есть ряд приятных возможностей вроде дедупликации строк в куче.

Наконец, был разработан ещё один новый алгоритм под названием Shenandoah. Он внесён в OpenJDK, но в Java 9 не появится, пока вы не станете использовать специальные билды Java из Red Hat (спонсора проекта). Алгоритм разработан с целью минимизации продолжительности пауз, невзирая на размер кучи, которая в то же время уплотняется. К недостаткам относятся большая избыточность кучи и ряд барьеров: для перемещения объектов во время выполнения приложения необходимо одновременно считывать указатель и взаимодействовать со сборщиком мусора. В этом смысле алгоритм аналогичен «безостановочному» сборщику из Azul.

Заключение

Цель этой статьи — не в том, чтобы убедить вас использовать другие языки или инструменты. Сборка мусора — это трудная, действительно трудная проблема, которая десятилетиями изучается армией учёных и программистов. Поэтому относитесь с подозрением к прорывным решениям, которые никто не заметил. Вероятнее всего, это просто странные или необычные замаскированные компромиссы, избегаемые другими по причинам, которые станут ясны позднее.

А если хотите минимизировать продолжительность пауз за счёт всех остальных параметров любой ценой, то обратитесь к сборщику мусора из Go.

Источник

Всё, что нужно знать о сборщике мусора в Python

Как правило, вам не нужно беспокоиться о сборщике мусора и работе с памятью когда вы пишете код на Python. Как только объекты больше не нужны, Python автоматически освобождает память из под них. Несмотря на это, понимание как работает GC поможет писать более качественный код.

Менеджер памяти

В отличие от других популярных языков, Python не освобождает всю память обратно операционной системе как только он удаляет какой либо объект. Вместо этого, он использует дополнительный менеджер памяти, предназначенный для маленьких объектов (размер которых меньше чем 512 байт). Для работы с такими объектами он выделяет большие блоки памяти, в которых в дальнейшем будет хранится множество маленьких объектов.

Как только один из маленьких объект удаляется — память из под него не переходит операционной системе, Python оставляет её для новых объектов с таким же размером. Если в одном из выделенных блоков памяти не осталось объектов, то Python может высвободить его операционной системе. Как правило, высвобождение блоков случается когда скрипт создает множество временных объектов.

Таким образом, если долгоживущий Python процесс с течением времени начинает потреблять больше памяти, то это совсем не означает, что в вашем коде есть проблема с утечкой памяти. Если вы хотите узнать больше о менеджере памяти в Python, вы можете прочитать об этом в другой моей статье (англ.).

Алгоритмы сборки мусора

Стандартный интерпретатор питона (CPython) использует сразу два алгоритма, подсчет ссылок и generational garbage collector (далее GC), более известный как стандартный модуль gc из Python.

Алгоритм подсчета ссылок очень простой и эффективный, но у него есть один большой недостаток. Он не умеет определять циклические ссылки. Именно из-за этого, в питоне существует дополнительный сборщик, именуемый поколенческий GC, который следит за объектами с потенциальными циклическими ссылками.

В Python, алгоритм подсчета ссылок является фундаментальным и не может отключен, тогда как GC опционален и может быть отключен.

Алгоритм подсчета ссылок

Алгоритм подсчета ссылок это одна из самых простых техник для сборки мусора. Объекты удаляются как только на них больше нет ссылок.

В Python, переменные не хранят значения, а выступают в роли ссылок на объекты. То есть когда вы присваивайте значение новой переменной, то сначала создается объект с этим значением, а уже потом переменная начинает ссылаться на него. На один объект может ссылаться множество переменных.

Каждый объект в Python содержит дополнительное поле (счетчик ссылок), в котором хранится количество ссылок на него. Как только кто-то ссылается на объект, это поле увеличивается на единицу. Если по какой-то причине ссылка пропадает, то это поле уменьшается на один.

Примеры, когда количество ссылок увеличивается:

Например, если удаляется список, то счетчик ссылок во всех его элементах уменьшается на один. Если все объекты внутри списка больше нигде не используются, то они также будут удалены.

Переменные, которые объявлены вне функций, классов и блоков называются глобальными. Как правило, жизненный цикл таких переменных равен жизни Python процесса. Таким образом, количество ссылок на объекты на которые ссылаются глобальные переменные никогда не падает до нуля.

Переменные, которые объявлены внутри блока (функции, класса) имеют локальную видимость (т.е. они видны только внутри блока). Как только интерпретатор питона выходит из блока он уничтожает все ссылки созданные локальными переменными внутри него.

Пример работы счетчика ссылок:

Основная причина, из-за которой стандартный интерпретатор (CPython) использует счетчик ссылок, является исторической. В настоящее время можно встретить множество дебатов по поводу данного подхода. Некоторые люди считают, что сборщик мусора может быть намного эффективней без участия алгоритма подсчета ссылок. У данного алгоритма есть множество проблем, таких как циклические ссылки, блокирование потоков, а также дополнительные накладные расходы на память и cpu.

Основным плюсом этого алгоритма является то, что объекты удаляются сразу как только они не нужны.

Дополнительный сборщик мусора

Зачем нам нужен дополнительный алгоритм, когда у нас уже есть подсчет ссылок?

К сожалению, классический алгоритм подсчета ссылок имеет один большой недостаток — он не умеет находить циклические ссылки. Циклические ссылки происходят когда один или более объектов ссылаются на друг друга.

Что такое сборщик мусора. Смотреть фото Что такое сборщик мусора. Смотреть картинку Что такое сборщик мусора. Картинка про Что такое сборщик мусора. Фото Что такое сборщик мусора

Как вы можете видеть, объект lst ссылается сам на себя, тогда как object1 и object2 ссылаются друг на друга. Для таких объектов счетчик ссылок всегда будет равен 1.

Демонстрация на Python:

Для того, чтобы исправить эту проблему, в Python 1.5 был добавлен дополнительный алгоритм, известный как модуль gc. Единственная задача которого удаление циклических объектов, к которым уже нет доступа из кода.

Циклические ссылки могут происходить только в “контейнерных” объектах. Т.е. в объектах, которые могут хранить другие объекты, например в списках, словарях, классах и кортежах. GC не следит за простыми и неизменяемыми типами, за исключением кортежей. Некоторые кортежи и словари так же исключаются из списка слежки при выполнении определенных условий. Со всеми остальными объектами гарантированно справляется алгоритм подсчета ссылок.

Когда GC срабатывает

В отличие от алгоритма подсчета ссылок, циклический GC не работает в режиме реального времени и запускается периодически. Каждый запуск сборщика создаёт микропаузы в работе кода, поэтому CPython (стандартный интерпретатор) использует различные эвристики, для определения частоты запуска сборщика мусора.

Циклический сборщик мусора разделяет все объекты на 3 поколения (генерации). Новые объекты попадают в первое поколение. Если новый объект выживает процесс сборки мусора, то он перемещается в следующее поколение. Чем выше поколение, тем реже оно сканируется на мусор. Так-как новые объекты зачастую имеют очень маленький срок жизни (являются временными), то имеет смысл опрашивать их чаще, чем те, которые уже прошли через несколько этапов сборки мусора.

В каждой генерации есть специальный счетчик и порог срабатывания, при достижении которых срабатывает процесс сборки мусора. Каждый счетчик хранит количество аллокаций минус количество деаллокаций в данной генерации. Как только в Python создается какой либо контейнерный объект, он проверяет эти счетчики. Если условия срабатывают, то начинается процесс сборки мусора.

Если сразу несколько или больше поколений преодолели порог, то выбирается наиболее старшее поколение. Это сделано из-за того, что старые поколения также сканируют все предыдущие. Чтобы сократить число пауз сборки мусора для долгоживущих объектов, самая старшая генерация имеет дополнительный набор условий.

Алгоритм поиска циклов

Для полноценного описания алгоритма поиска циклов потребуется отдельная статья. Если кратко, то GC итерирует каждый объект из выбранных поколений и временно удаляет все ссылки от отдельно взятого объекта (все ссылки на которые этот объект ссылается). После полного прохода, все объекты, у которых счетчик ссылок меньше двух считаются недоступными из питона и могут быть удалены.

Для более глубокого понимания я рекомендую прочитать (прим. переводчика: английский материал) оригинальное описание алгоритма от Neil Schemenauer и функцию collect из исходников CPython. Описание из Quora и пост о сборщике мусора так же могут быть полезны.

Стоит отметить, что проблема с деструкторами описанная в оригинальном описании алгоритма была исправлена начиная с Python 3.4 (подробнее в PEP 442).

Советы по оптимизации

Циклы зачастую случаются в реальных задачах, их можно встретить в задачах с графами, связными списками или в структурах данных, где требуется вести учёт отношений между объектами. Если ваша программа имеет высокую нагрузку и требовательна к задержкам, то, по возможности, циклы лучше избегать.

В некоторых случаях полезно отключить автоматическую сборку модулем gc и вызывать его вручную. Для этого достаточно вызывать gc.disable() и в дальнейшем вызывать gc.collect() вручную.

Как найти и отладить циклические ссылки

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

Как только вы определите проблемное место — его можно визуализировать с помощью objgraph.

Что такое сборщик мусора. Смотреть фото Что такое сборщик мусора. Смотреть картинку Что такое сборщик мусора. Картинка про Что такое сборщик мусора. Фото Что такое сборщик мусора

Заключение

Основной процесс сборки мусора выполняется алгоритмом подсчета ссылок, который очень простой и не имеет настроек. Дополнительный алгоритм используется только для поиска и удаления объектов с циклическими ссылками.

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

Источник

Избавляемся от мусора в Java

Что такое сборщик мусора. Смотреть фото Что такое сборщик мусора. Смотреть картинку Что такое сборщик мусора. Картинка про Что такое сборщик мусора. Фото Что такое сборщик мусора

Что такое сборка мусора, зачем она нужна и как работает

Для работы любого приложения требуется память. Однако память компьютера ограничена. Поэтому важно ее очищать от старых неиспользуемых данных, чтобы освободить место для новых.

Кто занимается этой очисткой? Как и когда очищается память? Как выглядит структура памяти? Давайте разберем с этим подробнее.

Структура памяти Java

Память в Java состоит из следующих областей:

Что такое сборщик мусора. Смотреть фото Что такое сборщик мусора. Смотреть картинку Что такое сборщик мусора. Картинка про Что такое сборщик мусора. Фото Что такое сборщик мусораСтруктура памяти Java

Native Memory — вся доступная системная память.

Stack (стек) — используется для хранения локальных переменных и стека вызовов метода. Для каждого потока выделяется свой стек.

Metaspace (метаданные) — в этой памяти хранятся метаданные классов и статические переменные. Это пространство также является общими для всех. Так как metaspace является частью native memory, то его размер зависит от платформы. Верхний предел объема памяти, используемой для metaspace, можно настроить с помощью флага MaxMetaspaceSize.

PermGen (Permanent Generation, постоянное поколение) присутствовало до Java 7. Начиная с Java 8 ему на смену пришла область Metaspace.

CodeCache (кэш кода) — JIT-компилятор компилирует часто исполняемый код, преобразует его в нативный машинный код и кеширует для более быстрого выполнения. Это тоже часть native memory.

Сборка мусора: введение

Что такое «мусор»? Мусором считается объект, который больше не может быть достигнут по ссылке из какого-либо объекта. Поскольку такие объекты больше не используются в приложении, то их можно удалить из памяти.

Например, на диаграмме ниже объект fruit2 может быть удален из памяти, поскольку на него нет ссылок.

Что такое сборщик мусора. Смотреть фото Что такое сборщик мусора. Смотреть картинку Что такое сборщик мусора. Картинка про Что такое сборщик мусора. Фото Что такое сборщик мусораМусор

Что такое сборка мусора? Сборка мусора — это процесс автоматического управления памятью. Освобождение памяти (путем очистки мусора) выполняется автоматически специальным компонентом JVM — сборщиком мусора (Garbage Collector, GC). Нам, как программистам, нет необходимости вмешиваться в процесс сборки мусора.

Что такое сборщик мусора. Смотреть фото Что такое сборщик мусора. Смотреть картинку Что такое сборщик мусора. Картинка про Что такое сборщик мусора. Фото Что такое сборщик мусораИсточник: Oracle.com

Сборка мусора: процесс

Для сборки мусора используется алгоритм пометок (Mark & Sweep). Этот алгоритм состоит из трех этапов:

Sweep (очистка). На этом шаге освобождается память, занятая объектами, не отмеченными на предыдущем шаге.

Compact (уплотнение). Объекты, пережившие очистку, перемещаются в единый непрерывный блок памяти. Это уменьшает фрагментацию кучи и позволяет проще и быстрее размещать новые объекты.

Что такое сборщик мусора. Смотреть фото Что такое сборщик мусора. Смотреть картинку Что такое сборщик мусора. Картинка про Что такое сборщик мусора. Фото Что такое сборщик мусораMark & Sweep GC

Поколения объектов

Что такое поколения объектов?

Для оптимизации сборки мусора память кучи дополнительно разделена на четыре области. В эти области объекты помещаются в зависимости от их возраста (как долго они используются в приложении).

Young Generation (молодое поколение). Здесь создаются новые объекты. Область young generation разделена на три части раздела: Eden (Эдем), S0 и S1 (Survivor Space — область для выживших).

Old Generation (старое поколение). Здесь хранятся давно живущие объекты.

Что такое сборщик мусора. Смотреть фото Что такое сборщик мусора. Смотреть картинку Что такое сборщик мусора. Картинка про Что такое сборщик мусора. Фото Что такое сборщик мусораПоколения в куче

Что такое Stop the World?

Когда запускается этап mark, работа приложения останавливается. После завершения mark приложение возобновляет свою работу. Любая сборка мусора — это «Stop the World».

Что такое гипотеза о поколениях?

Как уже упоминалось ранее, для оптимизации этапов mark и sweep используются поколения. Гипотеза о поколениях говорит о следующем:

Большинство объектов живут недолго.

Если объект выживает, то он, скорее всего, будет жить вечно.

Этапы mark и sweep занимают меньше времени при большом количестве мусора. То есть маркировка будет происходить быстрее, если анализируемая область небольшая и в ней много мертвых объектов.

Таким образом, алгоритм сборки мусора, использующий поколения, выглядит следующим образом:

Что такое сборщик мусора. Смотреть фото Что такое сборщик мусора. Смотреть картинку Что такое сборщик мусора. Картинка про Что такое сборщик мусора. Фото Что такое сборщик мусораСборка мусора поколениями

    Новые объекты создаются в области Eden. Области Survivor (S0, S1) на данный момент пустые.

    Когда область Eden заполняется, происходит минорная сборка мусора (Minor GC). Minor GC — это процесс, при котором операции mark и sweep выполняются для young generation (молодого поколения).

    После Minor GC живые объекты перемещаются в одну из областей Survivor (например, S0). Мертвые объекты полностью удаляются.

    По мере работы приложения пространство Eden заполняется новыми объектами. При очередном Minor GC области young generation и S0 очищаются. На этот раз выжившие объекты перемещаются в область S1, и их возраст увеличивается (отметка о том, что они пережили сборку мусора).

    При следующем Minor GC процесс повторяется. Однако на этот раз области Survivor меняются местами. Живые объекты перемещаются в S0 и у них увеличивается возраст. Области Eden и S1 очищаются.

    Объекты между областями Survivor копируются определенное количество раз (пока не переживут определенное количество Minor GC) или пока там достаточно места. Затем эти объекты копируются в область Old.

    Major GC. При Major GC этапы mark и sweep выполняются для Old Generation. Major GC работает медленнее по сравнению с Minor GC, поскольку старое поколение в основном состоит из живых объектов.

    Преимущества использования поколений

    Minor GC происходит в меньшей части кучи (

    2/3 от кучи). Этап маркировки эффективен, потому что область небольшая и состоит в основном из мертвых объектов.

    Недостатки использования поколений

    В каждый момент времени одно из пространств Survivor (S0 или S1) пустое и не используется.

    Сборка мусора: флаги

    В этом разделе приведены некоторые важные флаги, которые можно использовать для настройки процесса сборки мусора.

    Флаг

    Описание

    Первоначальный размер кучи

    Максимальный размер куча

    Отношение размера Old Generation к Young Generation

    Отношение размера Eden к Survivor

    Возраст объекта, когда объект перемещается из области Survivor в область Old Generation

    Типы сборщиков мусора

    Сборщик мусора

    Описание

    Преимущества

    Когда использовать

    Флаги для включения

    Использует один поток.

    Эффективный, т.к. нет накладных расходов на взаимодействие потоков.

    Работа с небольшими наборами данных.

    Использует несколько потоков.

    Многопоточность ускоряет сборку мусора.

    В приоритете пиковая производительность.

    Допустимы паузы при GC в одну секунду и более.

    Работа со средними и большими наборами данных.

    Для приложений, работающих на многопроцессорном или многопоточном оборудовании.

    Выполняет некоторую тяжелую работу параллельно с работой приложения.

    Может использоваться как на небольших системах, так и на больших с большим количеством процессоров и большим количеством памяти.

    Когда время отклика важнее пропускной способности.

    Паузы GC должны быть меньше одной секунды.

    Выполняет всю тяжелую работу параллельно с работой приложения.

    В приоритете время отклика.

    Сборщики мусора в Java

    Инструменты мониторинга GC

    Что мониторить?

    Частота запуска сборки мусора. Так как GC вызывает «stop the world», поэтому чем время сборки мусора меньше, тем лучше.

    Длительность одного цикла сборки мусора.

    Как мониторить сборщик мусора?

    Для мониторинга можно использовать следующие инструменты:

    Для включения логирования событий сборщика мусора добавьте следующие параметры JVM:

    Источник

    Добавить комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *