Разработка компилятора. Сборщик мусора


Notice: Функция get_currentuserinfo с версии 4.5.0 считается устаревшей! Используйте wp_get_current_user(). in /hlds/web/u138079p19/code4life.ru/htdocs/wp-includes/functions.php on line 3840

Сборка мусора не маловажная часть управления памятью, оперативная память не бесконечна. Говоря «сборщик мусора» обычно подразумевается объект сборщика мусора, который сам соберет все что наделал программист))

Так как большую часть времени программирую на C++, то о сборке мусора приходится думать самому.  Когда и что удалять? А когда выделять в куче либо на стеке? Но при разработке скриптового языка s4g сборка мусора была просто необходима. Необходимо оградить скриптера о заботе о памяти, если есть такая возможность упростить его жизнь то почему бы не сделать?)

Если говорить о ручном управлении памятью (на примере C++ new/delete программист сам знает когда и что удалить, но не всегда это делает), то тут нас ожидают две потенциально опасные проблемы:

  • висячие ссылки (dangling pointer) — память на которую ссылается ссылка уже освобождена, но ссылка не обнулена. Ссылка на вики
  • утечка памяти — память более не используется но уже недоступна для управления программистом и не освобождена и не передана системе в управление. Ссылка на вики

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

Сборка мусора (garbage collection) — форма управления памятью, когда неиспользуемые участки выделенной памяти освобождаются и возвращаются обратно под управление системой.

Сборщик мусора (garbage collector) — объект, программа или процесс который осуществляет сборку мусора.

При наличии сборщика мусора, сборка мусора осуществляется автоматически, либо при вызове функции запуска.

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

  • позволяет не думать о памяти
  • избавляет от висячих ссылок и утечек памяти
  • отрицательно влияет на производительность

То есть чтобы не думать о памяти и быть в безопасности придется жертвовать производительностью))

Виды сборки мусора:

  • на основании счетчика ссылок
  • на основании достижимости объектов (трассирующая)
  • сборка по поколениям

Сборка мусора на основании счетчика ссылок

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

Все просто. Данный метод существовал в s4g 0.9.0 и 0.9.1 версиях, и все работало как надо без утечек. Однако когда мы в s4g 0.9.2 начали делать классы то поняли что в некоторых случаях этот алгоритм не будет работать, а что бы он работал нужно много чего переделать, но и эти переделки не стоили бы того. Тогда мы внедрили сборку мусора на основании достижимости объектов.

Сборка мусора на основании достижимости объектов

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

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

Как оказалось на практике данный метод намного проще реализовать, а особой разницы в скорости мы не заметили.

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

Сборка мусора по поколениям

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

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

Оптимизация памяти

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

Уплотнение данных — это процесс при котором анализируются исходные данные и перемещаются ближе к началу.

К примеру был выделен массив объектов. После сборки мусора часть объектов была удалена (память выделенная под объект осталась но помечена как свободная), причем как в начале массива так и в середине и конце. Создание новых данных в данном случае будет дольше, потому что сначала надо найти первый свободный ключ в массиве, и только потом его надо инициализировать. затем если данные разбросаны по памяти то надо постоянно в памяти прыгать от 1 к 1000 к примеру, а не идти от 1 ко 2, то есть к следующему.

Поэтому необходимо производить уплотнение данных. В s4g мы используем этот метод.


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

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

В итоге, сборка мусора это не сложный процесс, достаточно понять проблему которую он решает и … столкнуться с ней, а дальше уже станет понятно как ее решать))

Поделиться:

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

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

*