perl 是否在一定范围内针对每个进行优化?



给定一个简单的程序:

use strict;
use warnings;
my $count = 0;
foreach ('a' .. 'zzzzzzzzzz') {
$count++;
}
print "$countn";

perl是否会在内存中创建大约1.4+e14个元素的整个范围,然后迭代它们,或者它是否有任何内部优化来一次简单地跳过范围运算符的一种状态?

好吧,我实际上已经运行了它,所以来自top的经验数据显示它是后者(它还没有完成看到来自time的数据(,但它是否记录在任何地方或在哪里可以找到来源的确认?

From perldoc perlop:

在当前的实现中,当 range 运算符用作foreach循环中的表达式时,不会创建临时数组,但是当您编写类似 [ 你写的]

是的,以下内容优化为计数循环:

for (EXPRX..EXPRY) { ... }

佩洛普提到了这一点。

在当前的实现中,当 range 运算符用作 foreach 循环中的表达式时,不会创建临时数组,但是 [低于 5.6 的 Perl 版本] 可能会在编写这样的东西时消耗大量内存:

for (1 .. 1_000_000) {
# code
}

您可以使用以下内容查看此信息:

$ perl -e'
my $n = 10_000_000;
system("ps h -o rss $$");
for (1..$n) { system("ps h -o rss $$"); last; }
'
1876
1944

即使在循环中,也只使用了 1944 KiB。这与循环之前分配的数量相同,远远不足以容纳 10,000,000 个标量。另一方面,以下略有不同的代码显示循环中使用了 385 MiB:

$ perl -e'
my $n = 10_000_000;
system("ps h -o rss $$");
for ((), 1..$n) { system("ps h -o rss $$"); last; }
'
1876
394724

在后一个版本中,分配了所有 1000 万个标量。

事实上,这不仅仅是EXPR..EXPR特别。以下所有方法的实现方式都不同:

  • for (EXPR; EXPR; EXPR)("C 样式的循环",增强的 while 循环。
    功能不同。
  • for (EXPRX..EXPRY)(一个范围,没有别的。
    递增计数循环。
  • for (reverse CONSTX..CONSTY)(一个常量范围,前面是反向。
    对编译时构建的数组索引的降序计数循环。[1]
  • for (reverse EXPRX..EXPRY)(一个变量范围,前面是反向。
    降序计数循环。
  • for (@ARRAY)(一个数组,没有别的。
    对数组索引进行计数循环。
  • for (reverse @ARRAY)(数组的反面,没有别的。
    数组索引上的降序计数循环。
  • for (reverse LIST)(任何不符合上述模式的列表。
    从头到尾迭代的扁平列表。
  • for (LIST)(不符合上述模式的任何列表。
    从头到尾迭代的扁平列表。

  1. 除了for (CONSTX..CONSTY)之外的任何地方,

    CONSTX..CONSTY
    

    经过优化,可以

    my @anon;
    BEGIN { @anon = CONSTX..CONSTY; }
    @anon
    

    你可以在这里看到这个:

    $ perl -e'
    BEGIN { system("ps h -o rss $$"); }
    system("ps h -o rss $$");
    exit(0);
    for (reverse 1..10_000_000) {  }
    '
    1868
    709540
    

最新更新