【问题标题】:Perl memory usage with map and file handle使用映射和文件句柄的 Perl 内存使用情况
【发布时间】:2011-08-30 15:08:30
【问题描述】:

在使用 perl 时调用map { function($_) } <FILEHANDLE>; 是否会将整个文件加载到内存中?

【问题讨论】:

    标签: perl file map memory-management filehandle


    【解决方案1】:

    是的——或者至少我是这样解释这个结果的。

    $ perl -e "map {0} <>" big_data_file
    Out of memory!
    
    $ perl -e "map {0} 1 .. 1000000000"
    Out of memory!
    

    人们可能想知道我们是否会因为 Perl 试图存储 map 的输出而耗尽内存。但是,我的理解是,Perl 已经过优化,可以在 void 上下文中调用 map 时避免这种工作。具体示例见this question中的讨论。

    也许是一个更好的例子

    $ perl -e "sub nothing {}  map nothing(), <>" big_data_file
    Out of memory!
    

    根据 cmets,问题的动机似乎是在处理大数据时希望使用紧凑的语法。

    open(my $handle, '<', 'big_data_file') or die $!;
    
    # An ordinary while loop to process a data file.
    while (my $line = <$handle>){
        foo($line);
    }
    
    # Here Perl assigns each line to $_.
    while (<$handle>){
        foo($_);
    }
    
    # And here we do the same thing on one line.
    foo($_) while <$handle>;
    

    【讨论】:

    • 一个足够简单的测试用例。谢谢。
    • 实际上,在这两种情况下,您都在加载带有0 值的列表。如果您使用 for 循环并将 push 归零到数组上,您将得到相同的错误。虽然在那种情况下,它不是瞬时的。
    • 我没有将返回的数据加载到数组中; map { print FILEHANDLE function($_) } &lt;FILEHANDLE&gt;;。我只是更喜欢在小型操作上使用 map 而不是 foreach。
    • @Eric Pruitt 替代方案如下:print FILEHANDLE function($_) while &lt;FILEHANDLE&gt;;
    • @FMc 有个主意。我不太明白这种语法是如何工作的(perl 的新手)。你能解释一下吗?
    【解决方案2】:

    是的,map、foreach 循环和 sub 调用的操作数在 map 之前计算,foreach 循环或 sub 调用甚至开始。

    一个例外:

    for my $i (EXPR_X..EXPR_Y)
    

    (有或没有my $i)被优化成一个计数循环,类似于

    my $x = EXPR_X;
    my $y = EXPR_Y;
    for (my $i = $x; $i <= $y; ++$i)
    

    Perl6 将原生支持惰性列表。

    【讨论】:

    • “子调用”是什么意思?
    • @Eric Pruitt, f(),参数是操作数。
    【解决方案3】:

    我假设您要问的问题是:map 函数是在文件开始处理之前对文件进行 slurp,还是逐行使用。

    让我们快速比较一下处理列表:

    while (<FILEHANDLE>) { ... }
    

    这个案例显然是逐行使用的。每次迭代都会获取$_ 的新值。

    for my $line (<FILEHANDLE>) { ... }
    

    在这种情况下,LIST 在循环开始之前被展开。在http://perldoc.perl.org/functions/map.html 中有一个对map 的引用,类似于foreach 循环,我相信LISTs 在传递给函数之前会被扩展。

    【讨论】:

    • 我认为在这种情况下没有实际意义:map { print FILEHANDLE function($_) } &lt;FILEHANDLE&gt;; 编辑:它似乎确实将文件加载到内存中(参见 FMc 的答案),所以我将使用 foreach 循环而不是地图。
    • @Eric 是的,你是对的.. 关于没有实际意义的问题没有明确的答案,因为 map 可以为所欲为。我会删除那部分..
    猜你喜欢
    • 2016-01-07
    • 2011-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-07
    • 2012-04-13
    • 2013-02-17
    • 2021-06-03
    相关资源
    最近更新 更多