首页 文章

随着Perl 6实现的成熟,我们可以期待什么性能提升?

提问于
浏览
24

每次我下载Rakudo Perl 6的新副本时,我都运行以下表达式,以了解其当前的性能:

say [+] 1 .. 100000;

并且速度一直在增加,但每次计算都有明显的延迟(几秒) . 作为比较,Perl 5(或其他解释语言)中的类似内容几乎立即返回:

use List::Util 'sum';

print sum(1 .. 100000), "\n";

或者在Ruby中(也几乎是即时的):

(1 .. 100000).inject(0) {|sum,x| sum+x}

将表达式重写为Perl6 loop 的结果大约是缩小范围的两倍,但对于简单计算,它仍然是一个非常明显的延迟(超过一秒):

my $sum;
loop (my $x = 1; $x <= 100000; $x++) {$sum += $x}

所以我的问题是,Perl6实现的哪些方面导致了这些性能问题?并且这应该随着时间的推移而改善,还是这个开销是Perl6使用的“一切都是对象”模型的不幸副作用?

最后, loop 构造比 [+] 减少算子更快?我认为循环会导致更多的总操作而不是减少 .

编辑:

如果可以的话,我会接受 mortiz 和_707268的答案 . 一切都是作为一个方法调用处理更直接的答案为什么 [+] 慢,所以一个人得到它 .

5 回答

  • 2

    关于缺乏优化,你必须要了解的另一件事是它复杂化了 . Rakudo的很大一部分是用Perl 6编写的 . 例如, [+] 运算符是通过方法 Any.reduce (用 $expression 设置为 &infix:<+> 调用)实现的,它具有内部循环

    for @.list {
        @args.push($_);
        if (@args == $arity) {
            my $res = $expression.(@args[0], @args[1]);
            @args = ($res);
        }
    }
    

    换句话说,reduce的纯perl实现,它本身由Rakudo运行 . 因此,您看到的代码不仅没有得到优化,而且您没有看到使代码运行的代码也没有得到优化 . 甚至 + 运算符的实例实际上也是方法调用,因为尽管 Num 上的 + 运算符是由Parrot实现的,但's nothing yet in Rakudo to recognize that you'已经有两个 Num 并且优化了方法调用,所以在Rakudo找到 multi sub infix:<+>(Num $a, Num $b) 之前有一个完整的动态调度并且意识到所有's really doing is an '添加' opcode. It'是一个合理的借口,比Perl 5慢100-1000倍:)

    更新8/23/2010

    More information from Jonathan Worthington关于Perl 6对象模型需要发生的各种变化(或者至少是Rakudo 's conception of it) to make things fast while retaining Perl 6' s "everything is method calls"性质 .

  • 2

    Rakudo如此缓慢有各种各样的原因 .

    第一个也许是最重要的原因是Rakudo还没有进行任何优化 . 目前的目标是更多探索新功能,并变得更加强大 . 你知道,他们说“首先使它运行,然后使其正确,然后使其快速” .

    第二个原因是parrot还没有提供任何JIT编译,垃圾收集器也不是最快的 . 有一个JIT编译器的计划,人们正在研究它(前一个被扯掉,因为它只是i386和维护噩梦) . 还有将Rakudo移植到其他虚拟机的想法,但这肯定会等到7月底之后 .

    最后,没有人能够真正地告诉我们有一个完整的,经过优化的Perl 6实现的速度有多快,但我确实认为它比现在要好得多 .

    顺便说一下你引用 [+] 1..$big_number 的情况可以在O(1)中运行,因为 1..$big_number 返回一个范围,这是内省的 . 因此,您可以使用 [+] Range 案例的总和公式 . 它再次完成了's something that could be done, but that hasn' .

  • 20

    它当然不是因为一切都是一个对象,因为没有理由为什么Perl 6必须比Perl 5或Ruby等其他语言的速度慢,但事实是Rakudo并不像perl或CRuby那样成熟 . 目前还没有太多的速度优化 .

  • 14

    我在2008年12月将这些内容提交给了Fefe's language competition . wp.pugs.pl 是Perl 5示例的字面翻译, wp.rakudo.pl 更加简单 . 我有两个程序,因为这两个程序实现了规范的不同子集 . 同时,构建信息已过时 . 消息来源:

    #!/usr/bin/env pugs
    # Pugs: <http://pugs.blogs.com/> <http://pugscode.org/>
    # prerequisite: ghc-6.8.x, not 6.10.x
    # svn co http://svn.pugscode.org/pugs/
    # perl Makefile.PL
    # make
    # if build stops because of haskeline, do:
    #   $HOME/.cabal/bin/cabal update ; $HOME/.cabal/bin/cabal install haskeline
    
    # learn more: <http://jnthn.net/papers/2008-tcpw-perl64danoob-slides.pdf>
    
    my %words;
    
    for =<> {
        for .split {
            %words{$_}++
        }
    }
    
    for (sort { %words{$^b} <=> %words{$^a} }, %words.keys) {
        say "$_ %words{$_}"
    }
    

    #!/usr/bin/env perl6
    # Rakudo: <http://rakudo.org/> <http://www.parrot.org/download>
    # svn co http://svn.perl.org/parrot/trunk parrot
    # perl Configure.pl
    # make perl6
    
    # Solution contributed by Frank W. & Moritz Lenz
    # <http://use.perl.org/~fw/journal/38055>
    # learn more: <http://jnthn.net/papers/2008-tcpw-perl64danoob-slides.pdf>
    
    my %words;
    
    $*IN.lines.split(/\s+/).map: { %words{$_}++ };
    
    for %words.pairs.sort: { $^b.value <=> $^a.value } -> $pair {
        say $pair
    }
    

    这些是2008年的结果:

    $ time ./wp.pugs.pl < /usr/src/linux/COPYING > foo
    
    real    0m2.529s
    user    0m2.464s
    sys     0m0.064s
    
    $ time ./wp.rakudo.pl < /usr/src/linux/COPYING > foo
    
    real    0m32.544s
    user    0m1.920s
    sys     0m0.248s
    

    今天:

    $ time ./wp.pugs.pl < /usr/src/linux/COPYING > foo
    
    real    0m5.105s
    user    0m4.898s
    sys     0m0.096s
    
    $ time ./wp.rakudo.pl < /usr/src/linux/COPYING > foo
    Divide by zero
    current instr.: '' pc -1 ((unknown file):-1)
    Segmentation fault
    
    real    0m3.236s
    user    0m0.447s
    sys     0m0.080s
    

    延迟补充:崩溃已在Why do I get 'divide by zero` errors when I try to run my script with Rakudo?处理 . Rakudo程序效率低下,见comments belowhttp://justrakudoit.wordpress.com/2010/06/30/rakudo-and-speed/ .

  • 4

    考虑到现在你的测试用例是optimized to an O(1) algorithm几乎立即返回,并且看起来几乎就像每周有几个优化;
    我期待全面的性能提升 .

    $ perl6 -e 'say [+] 1..10**1000; say now - INIT now'
    5000000000000000000000000000000000000000000000 ...
    0.007447
    

    即使这不是针对范围的特殊情况,它仍然比它快得多 .
    它现在可以在不到五分之一秒的时间内完成测试计算 .

    $ perl6 -e 'say [+] (1..100000).list; say now - INIT now'
    5000050000
    0.13052975
    

相关问题