【问题标题】:Using Perl6 to process a large text file, and it's Too Slow.(2014-09)使用 Perl6 处理大文本文件,速度太慢。(2014-09)
【发布时间】:2014-09-03 07:22:37
【问题描述】:

https://github.com/yeahnoob/perl6-perf中的代码宿主,如下:

use v6;

my $file=open "wordpairs.txt", :r;

my %dict;
my $line;

repeat {
    $line=$file.get;
    my ($p1,$p2)=$line.split(' ');
    if ?%dict{$p1} {
        %dict{$p1} = "{%dict{$p1}} {$p2}".words;
    } else {
        %dict{$p1} = $p2;
    }
} while !$file.eof;

“wordpairs.txt”较小时运行良好。

但是当“wordpairs.txt”文件大约有 140,000 行(每行,两个单词)时,它运行非常非常慢。即使运行 20 秒,它也无法完成自身。

它有什么问题?代码有问题吗?? 感谢任何人的帮助!

以下内容已添加 @ 2014-09-04,感谢 SE Answers 和 IRC@freenode#perl6 提供的许多建议

代码(目前,2014-09-04):

my %dict;
grammar WordPairs {
token word-pair { (\S*) ' ' (\S*) "\n" }
token TOP { <word-pair>* }
}
class WordPairsActions {
method word-pair($/) { %dict{$0}.push($1) }
}
my $match = WordPairs.parse(slurp, :actions(WordPairsActions));
say ?$match;

运行时间成本(目前):

$ time perl6 countpairs.pl wordpairs.txt
True
The pairs count of the key word "her" in wordpairs.txt is 1036

real    0m24.043s
user    0m23.854s
sys     0m0.181s

$ perl6 --version
This is perl6 version 2014.08 built on MoarVM version 2014.08

这个测试的时间性能目前不合理(因为相同的正确 Perl 5 代码只花费大约 160 毫秒),但比我原来的旧 Perl6 代码要好得多。 :)

PS。整个东西,包括原始测试代码、补丁和示例文本,都在 github 上。

【问题讨论】:

    标签: text large-files raku


    【解决方案1】:

    我使用与 Christoph 非常相似的代码对此进行了测试,使用包含 10,000 行的文件。大约需要 15 秒,正如您所说,这比 Perl 5 慢得多。我怀疑代码很慢,因为这段代码使用的东西没有看到 Rakudo 和 MoarVM 的其他部分最近收到的优化工作量。我确信代码的性能将在接下来的几个月中显着提高,因为任何缓慢的东西都会受到更多关注。

    当试图确定为什么某些 Perl 6 代码运行缓慢时,我建议在 MoarVM 上使用 --profile 运行 perl6 以查看它是否可以帮助您找到瓶颈。不幸的是,使用此代码,它将指向 rakudo 内部,而不是您可以改进的任何东西。

    当然值得在 irc.freenode.net 上与 #perl6 交谈,因为他们将拥有提供替代解决方案的知识,并且能够在未来提高其性能。

    【讨论】:

      【解决方案2】:

      Rakudo 并不以其出色的性能而闻名。

      使用更多地道的代码可能有帮助,也可能没有帮助:

      my %dict;
      for open('wordpairs.txt', :r).lines {
          my ($key, @words) = .words;
          push %dict{$key}, @words;
      }
      

      您还可以检查其他后端(Rakudo 在 MoarVM、Parrot 和 JVM 上运行),看看它是否在所有地方都同样慢。


      如果是缓慢的 IO 或处理,例如通过

      ,会很有趣
      my %dict;
      
      say 'start IO';
      my @lines = eager open('wordpairs.txt', :r).lines;
      say 'done IO';
      
      say 'start processing';
      for @lines { ... }
      say 'done processing';
      

      如果您想自己深入研究这个问题,我相信还有一个可用的分析器。

      【讨论】:

      • 用JVM/Parrot/MoarVM测试,所有运行时间不少于60秒。(我没有等待它的运行结果,几分钟后用Ctrl+C停止,完全没有反应.) 我认为这应该是某个地方的 BUG,因为几乎相同的 Perl 5 代码在我的 PC 上花费不到 200 毫秒。
      • 自上次发表评论以来,Rakudo 的这一领域已经取得了巨大的进步,特别是在 MoarVM 上。您可能需要重新审视这些基准。
      猜你喜欢
      • 1970-01-01
      • 2018-04-07
      • 2016-04-28
      • 1970-01-01
      • 2020-04-29
      • 2016-06-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多