Perl语言的效率及其他
上周偶然与fcicq讨论到一个关于perlcc的优化问题。 据说用perlcc将perl程序编译成C程序后再用gcc -O3进行优化,速度可能会快一些。 于是就测了测,顺便试了试其他语言的情况。
测试程序是Ackermann函数。 也许用它来做benchmark不太合适,但毕竟这是个纯数学+多次递归+耗时的运算,也能反映一定问题吧。
先来看Perl的原版。
$ cat ack.pl
#!/usr/bin/perl
sub ackermann {
my ( $m, $n ) = @_;
return $n + 1 if $m == 0;
return ackermann( $m - 1, 1 ) if $n == 0;
return ackermann( $m - 1, ackermann( $m, $n - 1 ) );
}
print ackermann( 3, 10 ), "\n";
$ time ./ack.pl
8189
real 1m5.044s
user 1m4.412s
sys 0m0.620s
结果约为65秒。然后用perlcc编译并gcc -O3优化试试:
$ cp /usr/lib/perl5/5.8.8/i386-linux-thread-multi/auto/DynaLoader/DynaLoader.a .
$ ar xv DynaLoader.a # 先弄个必要的DynaLoader.o否则会连接错误
$ perl -c -o ack-perlcc.c ack.pl
$ gcc -O3 -c -o ack-perlcc.o `perl -MExtUtils::Embed -e ccopts` ack-perlcc.c
$ gcc -o ack-perlcc `perl -MExtUtils::Embed -e ldopts` DynaLoader.o ack-perlcc.o
$ time ./ack-perlcc
8189
real 1m3.487s
user 1m3.012s
sys 0m0.484s
用了63秒,跟perl是同一数量级的。可见这个perlcc之后没什么效果。
遗憾之余顺手写了个纯C版本:
$ cat myack.c
#include <stdio.h>
int ackermann(int m, int n);
int main() {
int result = ackermann(3, 10);
printf("%d\n", result);
return 0;
}
int ackermann(int m, int n) {
if (m == 0) return n+1;
if (n == 0) return ackermann(m-1, 1);
return ackermann(m-1, ackermann(m, n-1));
}
$ gcc -O3 -o myack myack.c
$ time ./myack
8189
real 0m0.231s
user 0m0.228s
sys 0m0.004s
哇!0.23秒,比perl语言快了280倍以上。看来谈到效率时果然C语言才是王道。 也难怪为什么C程序员的待遇那么高了。
当然这个程序是纯粹的数学运算,发挥不出perl的长处,才会让perl效率如此低吧。
PHP也有同样的问题。还是这个Ackermann函数,用纯PHP写出来的效率很低, 但如果将函数写成php extension再调用,效率几乎等同于C语言的效率。 于是得出个结论,复杂的算法还是不要用PHP直接实现,而是写成extension吧。