【问题标题】:Perl map/grep memory leakPerl 映射/grep 内存泄漏
【发布时间】:2011-03-22 18:59:45
【问题描述】:

我在工作中一直在做一个 perl 项目,并且遇到了一个奇怪的内存泄漏。我将问题的根源归结为一个人为的例子:

#!/usr/bin/perl
use strict;
use warnings;

# takes: an array reference
# returns: 1
sub g {
    my ($a) = @_;
    return 1; 
}

# takes: nothing
# returns: the result of applying g on an array reference
sub f {
    my @a = ('a') x 131072; # allocate roughly a megabyte 
    return g(\@a); 
}

# causes a leak:
#map { f($_) } (1..100000); 

# loop equivalent to map, no leak:
#my @b;
#for my $i (1..100000) {
#    push @b, f($_);
#}

# causes a leak:
#grep { f($_) } (1..100000);

# loop equivalent to grep, no leak:
#my @b;
#for my $i (1..100000) {
#    push @b, $i if f($_);
#}

一次取消注释 4 个代码块中的 1 个(在子例程下方),并在监视其内存使用情况的同时运行脚本。在我的机器上,使用 grep 或 map 的代码似乎会导致内存泄漏,而“循环等效”则不会。我的 perl 版本是 v5.10.1,我正在运行 Ubuntu。

我相信这可能是 perl 中的一个错误,但我不想在没有关于可能原因的其他意见的情况下草率地得出结论。谁能解释这种行为是否正确?

谢谢

【问题讨论】:

    标签: perl memory-leaks map grep


    【解决方案1】:

    确实如此。但要证明这一点,您必须将 while(1){} 放在可疑表达式周围 - 在 perl 中,一旦获得的内存永远不会返回给操作系统(但可以由 perl 本身重用)。我已经用

    运行了代码

    while(1){ grep { f($_) } (1..100000) }

    低于 5.8.8 并且它的大小不断增长 - 所以,这是一个泄漏。

    【讨论】:

      【解决方案2】:

      我不知道这是否是内存泄漏。如果我降低循环的最高值(例如,从 100000 到 100),我可以重复使用 map/grep 表达式而不会丢失记忆。

      相反,mapgrep 在内存管理方面似乎更有可能是原子操作,perl 不会在这些操作中间执行垃圾收集。

      Perl 5.12.0(和 5.8.9)在这类表达式上似乎更健壮一些(但它们似乎也更慢)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-06
        • 2012-11-16
        • 2021-02-26
        相关资源
        最近更新 更多