Сборка мусора в Perl - PullRequest
       35

Сборка мусора в Perl

14 голосов
/ 04 июня 2010

В отличие от Java, Perl использует счетчик ссылок для сборки мусора. Я пытался найти некоторые предыдущие вопросы, которые говорят о C ++ RAII и умных указателях и Java GC, но я не понял, как Perl справляется с проблемой циклических ссылок.

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

Ответы [ 4 ]

13 голосов
/ 04 июня 2010

Согласно моей копии Программирование на Perl, 3-е изд. , при выходе из Perl 5 выполняется «дорогая разметка и разметка» для восстановления циклических ссылок. Вы должны избегать циклических ссылок в максимально возможной степени, потому что в противном случае они не будут возвращены до выхода из программы.

Perl 5 предлагает слабые ссылки через модуль Scalar :: Utils .

Perl 6 перейдет к подключаемой схеме сборки мусора (ну, у базовой машины будет несколько параметров сборки мусора , и поведение этих параметров может повлиять на Perl). То есть вы сможете выбирать между различными сборщиками мусора или реализовывать свои собственные. Хотите копирующий коллектор? Конечно. Хотите коллекционер красителей? Ты понял. Пометить / развернуть, уплотнить и т. Д.? Почему нет?

4 голосов
/ 20 ноября 2015

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

Если ваш код создает структуры данных с круговыми ссылками (т. Е. Дерево, узлы которого содержат ссылки обратно на корень), вы захотите использовать модуль Scalar :: Util, чтобы «ослабить» ссылки, указывающие на корневой узел. , Эти слабые ссылки не добавят к счетчику ссылок того, на что они указывают, поэтому вся структура данных будет автоматически освобождена при исчезновении последней внешней ссылки.

Пример:

use Scalar::Util qw(weaken);

...

    my $new_node = { content => $content, root => $root_node };
    weaken $new_node->{root};
    push @{$root_node->{children}}, $new_node;

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

1 голос
/ 04 июня 2010

Посмотрите на Прокси-объекты .

0 голосов
/ 04 июня 2010

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

...