Сборка мусора (информатика)

редактировать
Форма автоматического управления памятью

Остановка и копирование сборки мусора в архитектуре Lisp : память делится на рабочую и свободную; новые объекты (пары cons) размещаются в первом. Когда он заполнен (изображен), выполняется сборка мусора: все структуры данных, которые еще используются, обнаруживаются с помощью трассировки указателя и копируются в последовательные места в свободной памяти... ... После этого содержимое рабочей памяти отбрасывается в пользу сжатой копии, и роль рабочей и свободной памяти заменяется (изображено).

В информатике, сборка мусора (GC) является формой автоматической управление памятью. Сборщик мусора, или просто сборщик, пытается вернуть мусор или память, занятую объектами, которые больше не используются программой . Сборка мусора была изобретена американским ученым-компьютерщиком Джоном Маккарти примерно в 1959 году для упрощения ручного управления памятью в Лиспе.

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

Другие ресурсы, помимо памяти, такие как сетевые сокеты, база данных обрабатывает, окна взаимодействия с пользователем, файл и дескрипторы устройств, обычно не обрабатываются сборкой мусора. Методы, используемые для управления такими ресурсами, в частности, деструкторы, также могут быть достаточными для управления памятью, не оставляя необходимости в GC. Некоторые системы сборки мусора позволяют ассоциировать такие другие ресурсы с областью памяти, которая при сборе приводит к восстановлению этих ресурсов.

Содержание
  • 1 Принципы
    • 1.1 Преимущества
    • 1.2 Недостатки
  • 2 Стратегии
    • 2.1 Отслеживание
    • 2.2 Подсчет ссылок
    • 2.3 Анализ выхода
    • 2.4 Отметка времени и сердцебиение
  • 3 Доступность
    • 3.1 BASIC
    • 3.2 Objective-C
    • 3.3 Ограниченные среды
    • 3.4 Сборщики мусора для Java
    • 3.5 Использование во время компиляции
    • 3.6 Системы реального времени
  • 4 См. также
  • 5 Ссылки
  • 6 Дополнительная литература
  • 7 Внешние ссылки
Принципы

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

Многие языки программирования требуют сборки мусора либо как часть языковой спецификации (например, Java, C#, D,Go и большинство языков сценариев ) или эффективно для практической реализации (например, формальные языки, такие как лямбда-исчисление ); говорят, что это языки со сборкой мусора. Другие языки были разработаны для использования с ручным управлением памятью, но для них доступны реализации со сборкой мусора (например, C и C ++ ). Некоторые языки, такие как Ada, Modula-3 и C ++ / CLI, позволяют одновременно выполнять сборку мусора и ручное управление памятью. существовать в одном приложении с использованием отдельных куч для собранных и управляемых вручную объектов; другие, такие как D, собирают мусор, но позволяют пользователю вручную удалять объекты, а также полностью отключать сборку мусора, когда требуется скорость.

Хотя интеграция сборки мусора в компилятор языка и систему времени выполнения обеспечивает гораздо более широкий выбор методов, существуют системы post-hoc GC, такие как Automatic Подсчет ссылок (ARC), включая те, которые не требуют перекомпиляции. (Post-hoc GC иногда называют сборщиком мусора.) Сборщик мусора почти всегда будет тесно интегрирован с распределителем памяти.

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

Сборка мусора освобождает программиста от ручной работы с освобождением памяти. В результате некоторые категории ошибок устраняются или существенно сокращаются:

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

Некоторые из Ошибки, устраняемые сборкой мусора, влияют на безопасность.

Недостатки

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

Сборка мусора потребляет вычислительные ресурсы для принятия решения о том, какую память освободить, даже если программист, возможно, уже знал эту информацию. Штраф за удобство отсутствия аннотирования времени существования объекта вручную в исходном коде составляет накладные расходы, что может привести к снижению или неравномерной производительности. В рецензируемой статье 2005 года был сделан вывод, что GC требуется в пять раз больше памяти, чтобы компенсировать эти накладные расходы и работать так же быстро, как явное управление памятью. Взаимодействие с эффектами иерархии памяти может сделать эти накладные расходы невыносимыми в обстоятельствах, которые трудно предсказать или обнаружить при обычном тестировании. Влияние на производительность также было названо Apple причиной отказа от внедрения сборки мусора в iOS, несмотря на то, что это самая желанная функция.

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

Современные реализации GC пытаются минимизировать блокировку "stop-the-world ", выполняя как можно больше работы в фоновом режиме (т. Е. В отдельном потоке), например, отмечая недоступность мусора, пока процесс приложения продолжает работать. Несмотря на эти улучшения, например, в парадигме .NET CLR, по-прежнему очень трудно поддерживать большие кучи (миллионы объектов) с резидентными объектами, которые продвигаются до более старых поколений без заметных задержек (иногда несколько секунд).

Необходимость в явном ручном управлении ресурсами (выпуск / закрытие) для ресурсов без GC на объектно-ориентированном языке становится переходной для композиции. То есть: в недетерминированной системе сборки мусора, если для ресурса или подобного ресурсу объекта требуется ручное управление ресурсами (выпуск / закрытие), и этот объект используется как «часть» другого объекта, то составной объект также станет ресурсоподобный объект, который сам требует ручного управления ресурсами (выпуск / закрытие).

Стратегии

Трассировка

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

Подсчет ссылок

Подсчет ссылок Сборка мусора - это когда каждый объект подсчитывает количество ссылок на него. Мусор идентифицируется по нулевому счетчику ссылок. Счетчик ссылок на объект увеличивается при создании ссылки на него и уменьшается при уничтожении ссылки. Когда счетчик достигает нуля, память объекта освобождается.

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

Подсчет ссылок имеет ряд недостатков; это обычно может быть решено или смягчено более сложными алгоритмами:

Циклы
Если два или более объекта ссылаются друг на друга, они могут создать цикл, в котором ни один из них не будет собран, поскольку их взаимные ссылки никогда не позволяют их ссылкам счетчики становятся равными нулю. В некоторых системах сбора мусора, использующих подсчет ссылок (например, в CPython ), для решения этой проблемы используются специальные алгоритмы обнаружения цикла. Другая стратегия - использовать слабые ссылки для «обратных указателей», которые создают циклы. При подсчете ссылок слабая ссылка аналогична слабой ссылке при отслеживании сборщика мусора. Это специальный объект ссылки, существование которого не увеличивает счетчик ссылок объекта ссылки. Более того, слабая ссылка безопасна в том смысле, что когда объект-референт становится мусором, любая слабая ссылка на него утрачивается, вместо того, чтобы оставаться висящей, что означает, что она превращается в предсказуемое значение, такое как пустая ссылка.
Накладные расходы на пространство (счетчик ссылок)
Для подсчета ссылок необходимо выделить пространство для каждого объекта для хранения его счетчика ссылок. Счетчик может храниться рядом с памятью объекта или в дополнительной таблице где-то еще, но в любом случае каждый отдельный объект со счетчиком ссылок требует дополнительного хранилища для своего счетчика ссылок. Для этой задачи обычно используется пространство памяти с размером беззнакового указателя, что означает, что для каждого объекта необходимо выделить 32 или 64 бита хранилища счетчика ссылок. В некоторых системах можно уменьшить эти накладные расходы, используя тегированный указатель для хранения счетчика ссылок в неиспользуемых областях памяти объекта. Часто архитектура фактически не позволяет программам получать доступ ко всему диапазону адресов памяти, которые могут быть сохранены в ее собственном указателе размера; определенное количество старших битов адреса либо игнорируется, либо должно быть равно нулю. Если объект надежно имеет указатель в определенном месте, счетчик ссылок может храниться в неиспользуемых битах указателя. Например, каждый объект в Objective-C имеет указатель на свой класс в начале своей памяти; в архитектуре ARM64 с использованием iOS 7 19 неиспользуемых битов указателя этого класса используются для хранения счетчика ссылок на объект.
Накладные расходы на скорость (увеличение / уменьшение)
В наивных реализациях каждое присвоение ссылки и каждая ссылка, выходящая за пределы области видимости, часто требует модификации одного или нескольких счетчиков ссылок. Однако в общем случае, когда ссылка копируется из переменной внешней области видимости во внутреннюю переменную области видимости, так что время жизни внутренней переменной ограничено временем жизни внешней, приращение ссылки может быть исключено. Внешняя переменная «владеет» ссылкой. В языке программирования C ++ этот метод легко реализуется и демонстрируется с использованием ссылок const. Подсчет ссылок в C ++ обычно реализуется с помощью «интеллектуальных указателей », чьи конструкторы, деструкторы и операторы присваивания управляют ссылками. Интеллектуальный указатель может быть передан по ссылке на функцию, что позволяет избежать необходимости копировать-конструировать новый интеллектуальный указатель (который увеличит счетчик ссылок при входе в функцию и уменьшит его при выходе). Вместо этого функция получает ссылку на интеллектуальный указатель, который производится недорого. Метод подсчета ссылок Дойча-Боброу основан на том факте, что большинство обновлений счетчика ссылок фактически генерируется ссылками, хранящимися в локальных переменных. Он игнорирует эти ссылки, только подсчитывая ссылки в куче, но перед тем, как объект с нулевым счетчиком ссылок может быть удален, система должна проверить с помощью сканирования стека и зарегистрировать, что никакой другой ссылки на него еще не существует. Дальнейшее существенное снижение накладных расходов на обновления счетчиков может быть получено путем объединения обновлений, введенного Леванони и Петранком. Рассмотрим указатель, который в заданном интервале выполнения обновляется несколько раз. Сначала он указывает на объект O1, затем на объект O2и так далее, пока в конце интервала он не укажет на какой-то объект On. Алгоритм подсчета ссылок обычно выполняет rc (O1) -, rc (O2) ++, rc (O2) -, rc (O3) ++, rc (O3) -,..., rc (Вкл) ++. Но большинство этих обновлений избыточны. Для правильной оценки счетчика ссылок в конце интервала достаточно выполнить rc (O1) -и rc (On) ++. Леванони и Петранк измерили устранение более 99% обновлений счетчиков в типичных тестах Java.
Требуется атомарность
При использовании в многопоточной среде эти модификации (увеличивающие и уменьшающие) может потребоваться быть атомарными операциями, такими как сравнение и замена, по крайней мере, для любых объектов, которые совместно используются или потенциально совместно используются несколькими потоками. Атомарные операции дороги для мультипроцессора и даже дороже, если их нужно эмулировать с помощью программных алгоритмов. Этой проблемы можно избежать, добавив счетчики ссылок для каждого потока или процессора и обращаясь к глобальному счетчику ссылок только тогда, когда локальные счетчики ссылок становятся или больше не равны нулю (или, альтернативно, используя двоичное дерево счетчиков ссылок, или даже отказ от детерминированного уничтожения в обмен на отсутствие глобального счетчика ссылок вообще), но это добавляет значительные накладные расходы на память и, таким образом, имеет тенденцию быть полезным только в особых случаях (например, при подсчете ссылок модулей ядра Linux).. Объединение обновлений с помощью Levanoni и Petrank может использоваться для устранения всех атомарных операций с барьером записи. Счетчики никогда не обновляются потоками программы в процессе выполнения программы. Они изменяются только сборщиком, который выполняется как отдельный дополнительный поток без синхронизации. Этот метод можно использовать в качестве механизма остановки параллельных программ, а также с параллельным сборщиком подсчета ссылок.
Не в реальном времени
Наивные реализации подсчета ссылок обычно не обеспечивают реального -time, потому что любое присвоение указателя потенциально может вызвать рекурсивное освобождение ряда объектов, ограниченных только общим размером выделенной памяти, в то время как поток не может выполнять другую работу. Этой проблемы можно избежать, делегировав освобождение объектов, счетчик ссылок которых упал до нуля, другим потокам за счет дополнительных накладных расходов.

Анализ выхода

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

Timestamp Heartbeat

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

Доступность

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

Большинство языков функционального программирования, таких как ML, Haskell и APL, имеют встроенную сборку мусора. Lisp особенно примечателен как первый язык функционального программирования и первый язык, в котором реализована сборка мусора.

Другие динамические языки, такие как Ruby и Julia (но не Perl 5 или PHP до версии 5.3, в которых используется подсчет ссылок), JavaScript и ECMAScript также обычно используют GC. Объектно-ориентированное программирование языки, такие как Smalltalk и Java, обычно предоставляют интегрированную сборку мусора. Заметными исключениями являются C ++ и Delphi, которые имеют деструкторы.

BASIC

Исторически, языки, предназначенные для начинающих, такие как BASIC и Logo, часто использовали сборку мусора для типов данных переменной длины, размещенных в куче, таких как строки и списки, чтобы не обременять программистов ручным управлением памятью. На ранних микрокомпьютерах с их ограниченной памятью и медленными процессорами сборка мусора BASIC часто могла вызывать явно случайные, необъяснимые паузы в процессе работы программы.

Некоторые интерпретаторы BASIC, такие как Applesoft BASIC в семействе Apple II, неоднократно сканировали строковые дескрипторы для строки, имеющей наивысший адрес, чтобы сжать ее до высокая память, что приводит к производительности O (n), что может привести к минутным паузам при выполнении строковых программ. Заменяющий сборщик мусора для Applesoft BASIC, опубликованный в Call-APPLE (январь 1981, страницы 40–45, Randy Wigginton ), идентифицировал группу строк на каждом проходе по куче, время сбора резко. BASIC.System, выпущенная вместе с ProDOS в 1983 году, предоставляла оконный сборщик мусора для BASIC, который сокращал большинство сборок до долей секунды.

Objective-C

В то время как Objective-C традиционно не имел сборки мусора, с выпуском OS X 10.5 в 2007 Apple представила сборщик мусора для Objective-C 2.0 с использованием собственного сборщика времени выполнения. Однако с выпуском 2012 г. OS X 10.8 сборка мусора стала устаревшей в пользу LLVM автоматического счетчика ссылок (ARC), который был введен с OS X 10.7. Более того, с мая 2015 года Apple даже запрещает использование сборки мусора для новых приложений OS X в App Store. Для iOS сборка мусора никогда не применялась из-за проблем с реактивностью и производительностью приложения; вместо этого iOS использует ARC.

Ограниченные среды

Сборка мусора редко используется во встроенных системах или системах реального времени из-за обычной необходимости очень жесткого контроля над использованием ограниченных ресурсов. Однако были разработаны сборщики мусора, совместимые со многими ограниченными средами. Microsoft .NET Micro Framework, .NET nanoFramework и Java Platform, Micro Edition - это встраиваемые программные платформы, которые, как и их более крупные собратья, включают сборку мусора.

Сборщики мусора для Java

Некоторые популярные сборщики мусора, доступные в Java JDK, включают:

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

Использование во время компиляции

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

Эта форма сборки мусора была изучена на языке программирования Mercury, и она стала более широко использоваться с появлением автоматического счетчика ссылок LLVM . (ARC) в экосистему Apple (iOS и OS X) в 2011 году.

Системы реального времени

Были разработаны инкрементные, параллельные сборщики мусора и сборщики мусора в реальном времени, такие как алгоритм Бейкера или алгоритм Либермана.

В алгоритме Бейкера распределение выполняется в любой половине одной области памяти. Когда он заполняется наполовину, выполняется сборка мусора, которая перемещает живые объекты в другую половину, а оставшиеся объекты неявно освобождаются. Запущенная программа («мутатор») должна проверить, что любой объект, на который она ссылается, находится в правильной половине, и, если нет, переместить его, пока фоновая задача находит все объекты.

Генеральная сборка мусора схемы основаны на эмпирическом наблюдении, что большинство объектов умирают молодыми. При сборке мусора по поколениям сохраняются две или более области распределения (поколения), которые хранятся отдельно в зависимости от возраста объекта. Новые объекты создаются в «молодом» поколении, которое регулярно собирается, и когда поколение заполнено, объекты, на которые все еще ссылаются из более старых регионов, копируются в следующее старшее поколение. Иногда выполняется полное сканирование.

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

Большинство реализаций сборщиков мусора в реальном времени используют трассировку. Такие сборщики мусора в реальном времени соответствуют ограничениям жесткого реального времени при использовании с операционной системой реального времени.

См. Также
  • значок Портал компьютерного программирования
Ссылки
Дополнительная литература
Внешние ссылки
В Wikibook Управление памятью есть страница по теме: Сборка мусора
Последняя правка сделана 2021-05-21 11:49:30
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте