【问题标题】:Garbage collection in PerlPerl 中的垃圾收集
【发布时间】:2010-06-04 06:46:00
【问题描述】:

与 Java 不同,Perl 使用引用计数进行垃圾收集。我曾尝试搜索一些关于 C++ RAII 和智能指针以及 Java GC 的先前问题,但不了解 Perl 如何处理循环引用问题。

谁能解释 Perl 的垃圾收集器如何处理循环引用?有没有办法回收程序不再使用的循环引用内存,或者 Perl 完全忽略了这个问题?

【问题讨论】:

    标签: perl garbage-collection circular-reference


    【解决方案1】:

    根据我的Programming Perl 3rd ed.副本,在退出 Perl 5 时会执行“昂贵的标记和扫描”来回收循环引用。您需要尽可能避免循环引用,否则在程序退出之前它们不会被回收。

    Perl 5 确实通过 Scalar::Utils 模块提供弱引用。

    Perl 6 将转向可插入的垃圾收集方案(好吧,underlying VM will have multiple garbage collection options 和这些选项的行为会对 Perl 产生影响)。也就是说,您将能够在各种垃圾收集器之间进行选择,或者实现您自己的。想要一个复制收藏家?当然。想要着色器?你说对了。标记/扫描、压缩等?为什么不呢?

    【讨论】:

    • Nit:Perl 5 使用引用计数。这是一个垃圾收集方案。
    • 好的,我修改了对 Perl 6 垃圾回收的引用。
    • 感谢您更新答案。注意:可插拔垃圾收集器似乎是一个可怕的想法。当插入对 GC 时间做出不同承诺的垃圾收集器时,这是一种减慢速度和/或在远处产生可疑行为的好方法。
    • 我不知道他们为什么选择可插拔架构,除了 (1) 说“这确实是实现定义的领域”和 (2) 避免做出决定。他们还采用了可插拔的正则表达式架构,这对我来说更没有意义。
    • 引用计数不是垃圾收集。它是自动内存管理。没有运行收集器算法来回收不再使用的内存。
    【解决方案2】:

    快速回答是 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;
    

    如果您在向数据结构中添加新节点时使用这样的代码,那么实际计算的对根的唯一引用是来自结构外部的引用。这正是你想要的。然后,一旦对它的最后一个外部引用消失,就会回收根及其所有子节点。

    【讨论】:

      【解决方案3】:

      看看Proxy Objects

      【讨论】:

        【解决方案4】:

        Perl 在某些情况下(我认为当一个线程死掉时)应用标记和清除备用 GC 以回收循环引用。请注意,“每个值都是字符串”Perl 节使得创建真正的循环引用变得困难;这是可行的,但“正常”的 Perl 代码不可行,这就是引用计数在 Perl 中运行良好的原因。

        【讨论】:

        • 泄露一个 SV perl 调用的快速方法sub leak { my $r; $r = \$r; } 虽然这是一个人为的例子,但在不注意的情况下做同样的事情并不难。
        • 这是完全错误的; Perl 确实相信每个值都是一个字符串。 my $hashref = { a => 1 }; 留下 $hashref 作为实际参考,而不是字符串。自 17 年前 1994 年 10 月问世的 Perl 5 以来,情况就是如此。 (当然,Perl 很乐意将引用转换为字符串,但这种转换是单向的)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-01-21
        • 1970-01-01
        • 2018-12-30
        • 1970-01-01
        • 2011-02-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多