每次我下载了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循环结束的速度是减少范围的两倍,但是对于简单计算,它仍然是非常明显的延迟(超过一秒):
my $sum; loop (my $x = 1; $x <= 100000; $x++) {$sum += $x}
所以我的问题是,Perl6实现的哪些方面导致这些性能问题?而且应该随着时间的推移而改善,还是Perl6正在使用的“一切都是一个对象”的模式呢?
最后,循环结构如何比[减少运算符更快?我会认为循环将导致比减少更多的操作。
编辑:
如果可以的话,我会接受愚蠢和爱好者的回答。所有这些都被处理为一种方法调用更直接地解释为什么[]是缓慢的,所以一个人得到它。
解决方法
另一件你必须了解的缺乏优化是复杂的。 Rakudo的大部分是用Perl 6编写的。所以例如[]运算符是通过Any.reduce(用$ expression设置为& infix:调用的)方法来实现的,它的内部循环
for @.list { @args.push($_); if (@args == $arity) { my $res = $expression.(@args[0],@args[1]); @args = ($res); } }
换句话说,一个纯粹的perl实现的reduce,它本身正在由Rakudo运行。所以你不仅可以看到没有得到优化的代码,你看不到代码运行的代码也没有得到
优化。即使操作符的实例实际上是方法调用,因为尽管Num上的操作符是由Parrot实现的,但是在Rakudo中还没有什么可以识别出你有两个Num并优化了方法调用,所以在Rakudo之前有一个完整的动态调度发现多子中缀: >(Num $ a,Num $ b),并意识到所有它真正在做的是一个“添加”操作码。这是一个合理的借口,比Perl 5慢100-1000倍:)
更新8/23/2010
More information from Jonathan Worthington关于Perl 6对象模型(或至少Rakudo的概念)需要发生的变化,以保持Perl 6的“一切都是方法调用”的性质,使事情变得快速。