Сборщики мусора — еще одно доказательство того, что люди не умеют упрощать вещи. Все наоборот.

Сборщики мусора упрощают разработку малых и крупных приложений с каждым шагом. Мне приходит в голову вопрос, полезен ли сборщик мусора? Да, точка. Современные языки программирования предоставляют сборщики мусора, чтобы сделать управление памятью абстрактным для программистов. В таких языках, как C и C++, которые не реализуют никаких сборщиков мусора, ответственность за управление памятью лежит на программисте. Другими словами, вам нужно доверять людям, что хорошо, но это может быть сделано плохо. Управление памятью — очень сложная область компьютерных наук, и существует множество способов решения этой задачи. [1] Эту сложность можно облегчить программистам с помощью сборщиков мусора. Первый сборщик мусора был создан примерно в 1959 году Джоном Маккарти, чтобы «абстрагироваться от ручного управления памятью в Лиспе», который был разработан им самим. [2] Сборщики мусора обозначаются как противоположность ручному управлению памятью. «Основные принципы сборщиков мусора заключаются в том, чтобы найти объекты данных в программе, к которым нельзя будет получить доступ в будущем, и восстановить ресурсы, используемые этими объектами». [2] Для достижения этих целей ученые-компьютерщики активно пытались разработать алгоритмы, делающие сборщики мусора надежными и эффективными. Вот некоторые из этих алгоритмов: «подсчет ссылок», «остановка и копирование», «отметка и очистка».

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

Подсчет ссылок — это метод, реализованный в различных сборщиках мусора, которые можно найти в популярных языках программирования. Одним из популярных и современных языков программирования, который использует подсчет ссылок в реализации своего сборщика мусора, является CPython. Для справки: CPython — наиболее широко используемый интерпретатор Python, написанный на языке C, отсюда и название. [3] Техника подсчета ссылок заключается в подсчете общего количества ссылок на объект. Если количество ссылок на объект равно нулю, это означает, что к этому объекту нельзя получить доступ, что означает, что этот объект может быть удален, другими словами, освобожден. В C или C++ эта идея будет заключаться в том, «сколько указателей ссылается на этот объект». [4] Если указатель копируется, счетчик увеличивается. Когда указателю присваивается что-то еще, то есть другой объект, счетчик уменьшается. То же самое происходит, когда конкретный указатель выходит за пределы области видимости, счетчик также уменьшается, потому что время жизни этого указателя завершено. Подсчет ссылок сам по себе, на мой взгляд, не лучший подход для сборщика мусора из-за следующей идеи. Пусть A и B будут двумя объектами, где A имеет ссылку на B, а B имеет ссылку на A. Эти два объекта всегда будут иметь счетчик больше единицы, другими словами, они никогда не будут собраны/освобождены сборщиком мусора. используя подсчет ссылок сам по себе. Это явление называется циклами ссылок. Решение состоит в том, чтобы периодически обнаруживать любое возникновение этих циклов и освобождать эту память. Главное преимущество использования подсчета ссылок в том, что он не требует длительных пауз при работе сборщика мусора и имеет «четко определенное время жизни каждого объекта». [5] Как мы видим, у этого метода есть своя цена, и, как всегда, это выбор разработчиков языка программирования, использовать его или нет.

Отметить и развернуть

Другим подходом к решению этой проблемы является пометка и очистка, которая была «первым разработанным алгоритмом сборки мусора, способным восстанавливать циклические структуры данных». [7] Основная идея пометки и очистки состоит в том, чтобы пройти по дереву, имеющему ссылки на все объекты, и пометить их, если они доступны из корня. А поскольку на этот объект имеется ссылка, это означает, что этот объект жив. После маркировки всех этих объектов сборщик мусора переходит к фазе очистки, которая в основном освобождает все материалы, которые не были отмечены фазой маркировки. Другими словами, все, до чего не удалось добраться, является мусором и может быть утилизировано/использовано повторно. Основное преимущество метода пометки и очистки состоит в том, что он способен распознавать и очищать опорные циклы, поскольку этот метод обращается к объектам из корня дерева. В этом заключается главное преимущество маркировки и очистки перед подсчетом ссылок. Эта концепция мощная, но не идеальная. Эти подходы имеют те же затраты, что и ручное выделение и освобождение памяти. Причина в том, что когда фаза очистки завершена, у нас остаются некоторые разделы, которые были освобождены между некоторыми объектами, и, как говорится, все еще трудно перейти и перераспределить это освобожденное пространство. Решением этой проблемы является остановка и копирование, о котором я расскажу в следующем абзаце. Другая проблема с пометкой и очисткой заключается в том, что для запуска сборщика мусора программа должна быть технически остановлена, а это может быть неудобно, если программа должна взаимодействовать с пользователями. Эта концепция известна как «остановить мир», что в основном означает, что программа не будет отвечать, пока работает сборщик мусора.

Остановить и скопировать

«Остановить и скопировать» — еще один прием, значительно улучшающий «отметить и убрать», но, как и все остальное, он имеет свою цену. Идея остановки и копирования «состоит в том, чтобы переупорядочить кучу так, чтобы все свободное пространство было непрерывным». [8] Другими словами, все объекты организованы таким образом, что легко определить, где находится неиспользуемое пространство в памяти. Помните, что мы говорили о маркировке и развертке; на этапе очистки у нас есть дыры в свободной памяти между объектами, которые трудно отслеживать. Stop-and-copy использует другой подход для решения этой проблемы.

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

Поколенческая сборка мусора

Еще один очень известный метод — сборка мусора поколений. Этот метод состоит в перемещении объектов в зависимости от времени, в течение которого этот объект был живым. Например, предположим, что сборщик мусора запускается несколько раз, и конкретный объект все еще жив после нескольких попыток, этот объект, вероятно, будет жить до конца программы. Эта концепция вводит идею классификации объектов по продолжительности их жизни. Эти категории, то есть ярлыки, широко известны как «молодое поколение», «старое поколение» и «постоянное поколение». [9] В категории молодого поколения находятся все вновь выделенные объекты. «Поскольку большинство объектов вскоре становятся недоступными, многие объекты создаются в молодом поколении, а затем исчезают». Это считается «мелкой сборкой мусора». [9] Идея заключается в том, что большинство объектов не имеют длительного срока службы. Когда функция возвращается, скорее всего, все ее объекты умрут и нет смысла их сохранять. Если сборщик мусора запускался несколько раз, в зависимости от реализации сборщика мусора объект, который не освобождается из категории молодого поколения, может получить «повышение». Продвижение — это, по сути, перемещение объектов молодого поколения в категорию старшего поколения.

«Сюда копируются объекты, которые не стали недосягаемыми и уцелели от молодого поколения». [9] Здесь сборка мусора происходит реже, потому что эти объекты, скорее всего, живут дольше, чем другие, в молодом поколении. Если объект собран правильно и освобожден здесь, говорят, что это «крупная сборка мусора». [9] Постоянное поколение предназначено для функций и/или классов. Хотя сборка мусора все еще может происходить здесь, это не место для перемещения/продвижения объектов, переживших несколько итераций сборки мусора в старом поколении. Если сборка происходит в постоянном поколении, мы также называем это «крупной сборкой мусора». [9]

Собранный мусор и несобранные языки

Теперь давайте рассмотрим два разных языка программирования, один со сборкой мусора и один без сборки мусора, и то, как программисты ведут себя по-разному, используя эти две идеи. Большинство языков программирования, которые имеют встроенную автоматическую очистку памяти, большую часть времени предоставляют общедоступный API для сборщика мусора, что позволяет вам играть с ним и даже отключать его. Если вы раньше использовали Python, вполне вероятно, что вы никогда не использовали ключевое слово «del». И ладно, потому что это совсем не нужно. В C++ требуется, если вы вручную выделяете память, т. е. 'new', и malloc() в C. Нагрузка на эти языки программирования без сбора мусора заключается в том, что при разработке объектов вам нужно научить эти объекты, как удалять себя . Например, в C++ это деструктор, а в Python или Java вам не нужно ничего указывать. Реализация деструктора может показаться простой, и это зависит от сложности вашего объекта, но это может привести к ошибкам во время выполнения в вашей программе, и это тип ошибок, с которыми вы не хотите сталкиваться. Хотя это может показаться естественным, если вы разработчик C++, это одна из задач, которая заставляет программистов использовать другие языки, такие как Java или Python, которые предоставляют свой собственный механизм сборщиков мусора.

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

Источник:

[1] http://www.memorymanagement.org/mmref/begin.html

[2] https://en.wikipedia.org/wiki/Garbage_collection_(computer_science)

[3] https://en.wikipedia.org/wiki/CPython

[4] https://mortoray.com/2012/01/08/what-is-reference-counting/

[5] https://en.wikipedia.org/wiki/Reference_counting

[6] http://doc.cat-v.org/inferno/concurrent_gc/concurrent_gc.pdf

[7] http://www.brpreiss.com/books/opus5/html/page424.html

[8] http://www.cs.princeton.edu/courses/archive/spr96/cs441/notes/l14.html

[9] http://www.cubrid.org/blog/dev-platform/understanding-java-garbage-collection/

[10] http://www.albanyny.gov/Government/Departments/GeneralServices/TrashRecycling/GarbageCollection.aspx

[11] https://secweb.cs.odu.edu/~zeil/cs361/web/website/Lectures/garbageCollection/pages/referenceCounting.html

[12] http://www.brpreiss.com/books/opus5/html/page424.html

[13] http://www.brpreiss.com/books/opus5/html/page427.html

[14] «http://www.pointsoftware.ch/en/under-the-hood-garbage-collection-part-1- Different-object-life-cycles-short-and-long-term-requires- Different- вывоз мусора/"