上一篇:如何寻找优秀程序员 - 下一篇:一张A4纸折出2CD的封套
版权声明:可以任意转载,但转载时必须标明原作者charlee、原始链接http://tech.idv2.com/2008/01/29/perlcc-optimize/以及本声明。
上周偶然与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吧。
2008-01-29 19:55
试了,好像差不多… :(
2008-01-30 14:46
谢谢,改过来了
2008-02-04 00:37
Perl的“效率”不光是执行的效率,开发也有效率的咯:)
2008-02-04 09:36
@Yurii 的确——高级语言可以说就是用执行效率换取开发效率,毕竟现在硬件要比人工便宜多了。从这个角度来说,员工培训实际上就是在提高开发效率。
2008-04-05 21:18
测试了一下 microperl, ack(3,7), perl 0.8s, microperl 更慢, 1.1s.
2008-06-29 17:37
再添一句, lua 的速度不错 :D
lua(3,10)
real 0m8.483s
user 0m8.395s
sys 0m0.010s

2008-01-29 18:39
$ gcc -c -o ack-perlcc.o `perl -MExtUtils::Embed -e ccopts` ack-perlcc.c —- ms 应该在这个地方 O3…快改快改…