Text 使用Perl6处理大型文本文件,它';太慢了。(2014-09)

Text 使用Perl6处理大型文本文件,它';太慢了。(2014-09),text,large-files,raku,Text,Large Files,Raku,主机中的代码如下所示: 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

主机中的代码如下所示:

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”文件大约有140000行(每行两个字)时,它的运行速度非常慢。即使跑了20秒,它也无法自行完成

有什么问题吗?代码中有错误吗?? 谢谢任何人的帮助

添加了以下内容@2014-09-04,感谢SE回复和IRC@freenode#perl6 代码(目前,2014-09-04):

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


另外,整个过程,包括原始测试代码、补丁和示例文本,都在github上。

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';

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

我已经用与Christoph使用一个包含10000行的文件非常相似的代码测试了这个问题。它大约需要15秒,正如您所说,这比Perl5要慢得多。我怀疑这段代码的速度很慢,因为这段代码使用的东西没有像Rakudo和MoarVM的其他部分最近收到的那样多的优化效果。我确信,在接下来的几个月里,代码的性能将显著提高,因为任何慢的东西都会受到更多的关注

当试图确定某些Perl 6代码的速度慢的原因时,我建议使用--profile在MoarVM上运行perl6,看看它是否有助于找到瓶颈。不幸的是,这段代码将指向rakudo内部,而不是您可以改进的任何内容


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

使用JVM/Parrot/MoarVM进行测试,所有运行时间都不少于60秒。(我没有等待它的运行结果,并在几分钟后使用Ctrl+C停止它,完全没有响应。)我认为这应该是一个BUG,因为几乎相同的Perl 5代码在我的PC上花费不到200毫秒。自上次评论以来,Rakudo的这一领域已经取得了巨大的进步,特别是在MoarVM上。您可能希望重新访问这些基准测试。
my %dict;
for open('wordpairs.txt', :r).lines {
    my ($key, @words) = .words;
    push %dict{$key}, @words;
}
my %dict;

say 'start IO';
my @lines = eager open('wordpairs.txt', :r).lines;
say 'done IO';

say 'start processing';
for @lines { ... }
say 'done processing';