Why is my Python version slower than my Perl version?
我做Perl已经10多年了,但一个朋友说服我尝试Python,告诉我它比Perl快多少。因此,我把一个用Perl编写的应用程序移植到了Python上,发现它的运行速度慢了3倍。最初我的朋友告诉我,我一定是做错了,所以我重写和重构,直到我不再重写和重构…它还是慢得多。所以我做了一个简单的测试:
1 2 3 4 5 6 7 8 | i = 0 j = 0 while (i < 100000000): i = i + 1 j = j + 1 print j |
$ time python python.py
100000000real 0m48.100s
user 0m45.633s
sys 0m0.043s
1 2 3 4 5 6 7 8 9 | my $i = 0; my $j = 0; while ($i < 100000000) { ++$i; # also tested $i = $i + 1 to be fair, same result ++$j; } print $j; |
$ time perl perl.pl
100000000real 0m24.757s
user 0m22.341s
sys 0m0.029s
只是慢了两倍,这似乎没有反映出我见过的任何基准…我的安装有问题吗,或者python真的比perl慢得多?
挑剔的答案是,您应该将其与惯用的python进行比较:
- 原始代码在我的机器上需要34秒。
- 带
+= 和xrange() 的for 循环(florianh的答案)需要21。 - 把整个东西放到一个函数中可以将其缩短到9秒!这比Perl(我机器上的15秒)快得多!说明:python局部变量比全局变量快得多。(为了公平起见,我还尝试了Perl中的函数-无更改)
去掉j变量将其缩短为8秒:
print sum(1 for i in xrange(100000000))
python有一个奇怪的特性,即较高级别的较短代码往往是最快的:—)
但真正的答案是你的"微观基准"毫无意义。语言速度的真正问题是:平均实际应用程序的性能如何?要知道这一点,您应该考虑到:
复杂代码中的典型操作组合。您的代码不包含任何数据结构、函数调用或OOP操作。
一个足够大的代码库来感受缓存效果——许多解释器优化都是以内存换速度,这是任何微小的基准都无法公平衡量的。
优化机会:编写代码后,如果速度不够快,你能轻而易举地跑多快?
例如,将沉重的负担转移到有效的诽谤中有多困难?
Pypy的基准和辛烷值是现实语言速度基准的很好例子。
如果你想谈论数字运算,Python在科学家中非常受欢迎。他们喜欢它简单的伪数学语法和短的学习曲线,也喜欢它优秀的numpy库用于数组处理和包装其他现有的C代码。
还有psyco-jit,它可能在1秒内运行得很好,但是我现在不能检查它,因为它只能在32位x86上工作。编辑:现在,跳过psyco,使用pypy,这是一个跨平台的积极改进jit。
所有这些微观基准测试都会变得有点愚蠢!
例如,在两个python&perl中只需切换到
1 2 3 4 5 6 7 | my $j = 0; for my $i (1..100000000) { ++$j; } print $j; |
< BR>我可以用这个剃掉更多的头发:
1 2 | ++$j for 1..100000000; print $j; |
< BR>更愚蠢的是,我们可以把它降到1秒以下;-)
1 | print {STDOUT} (1..10000000)[-1]; |
/I3AZ/
参考:使用Perl 5.10.1。
在python中,这段代码是:
1 2 3 4 | j = 0 for i in range(10000000): j = j + 1 print j |
是一样的
1 | print range(10000001)[-1] |
在我的机器上,
1 2 3 4 5 6 | $ time python test.py 10000000 real 0m1.138s user 0m0.761s sys 0m0.357s |
运行大约1s.range()(或xrange)是python内部的,并且"内部"它已经可以为您生成一个数字序列。因此,您不必使用自己的循环来创建自己的迭代。现在,您可以找到一个Perl等价物,它可以运行1秒来产生相同的结果。
如果您使用正确的Python语言语法,那么Python运行得非常快。它被粗略地描述为"Python"。
如果您像这样重新构造代码,那么它的运行速度至少是我的机器的两倍:
1 2 3 4 | j = 0 for i in range(10000000): j = j + 1 print j |
在Python中使用while时,应该检查是否也可以使用"for x in range()"。
python在数字计算方面不是特别快,我敢肯定在文本处理方面比perl慢。
由于您是一个经验丰富的Perl手,我不知道这是否适用于您,但从长远来看,Python程序更易于维护,开发速度更快。在大多数情况下,速度是"足够的",当您真正需要性能提升时,您可以灵活地降到C。
更新可以。我刚刚创建了一个大文件(1GB),其中包含随机数据(大部分是ASCII),并将其分成等长的行。这应该模拟一个日志文件。
然后,我运行简单的Perl和Python程序,逐行搜索文件中的现有模式。
对于python 2.6.2,结果是
1 2 3 | real 0m18.364s user 0m9.209s sys 0m0.956s |
使用Perl 5.10.0
1 2 3 | real 0m17.639s user 0m5.692s sys 0m0.844s |
程序如下(如果我做了蠢事请告诉我)
1 2 3 4 5 6 7 8 9 10 | import re regexp = re.compile("p06c") def search(): with open("/home/arif/f") as f: for i in f: if regexp.search(i): print"Found : %s"%i search() |
和
1 2 3 4 5 6 7 8 9 | sub search() { open FOO,"/home/arif/f" or die $!; while (<FOO>) { print"Found : $_ " if /p06c/o; } } search(); |
结果非常接近,这样或那样的调整似乎不会改变结果。我不知道这是否是一个真正的基准,但我认为这将是我用两种语言搜索日志文件的方式,所以我对相关性能进行了修正。
谢谢克里斯。
python在字典中维护全局变量。因此,每次有一个赋值时,解释器都会在模块字典上执行查找,这有点昂贵,这就是为什么您发现您的示例如此缓慢的原因。
为了提高性能,您应该使用本地分配,比如创建一个函数。python解释器在数组中存储局部变量,访问速度更快。但是,应该注意到这是cpython的一个实现细节;例如,我怀疑Ironpython会导致完全不同的结果。
最后,为了获得关于这个主题的更多信息,我建议您从gvr获得一篇有趣的文章,关于Python中的优化:Python模式——一个优化轶事。
python比perl慢。开发速度可能更快,但执行速度却不更快。这里有一个基准http://xodian.net/serendipity/index.php?/archives/27-benchmark-php-vs.-python-vs.-perl-vs.-ruby.html-edit-一个糟糕的基准,但它至少是一个有数字的真正基准,而不是一些猜测。坏的是,除了循环之外,没有其他源或测试。
我不是最新的关于Python的所有内容,但我对这个基准的第一个想法是Perl和Python数字之间的差异。在Perl中,我们有数字。它们不是对象,它们的精度仅限于体系结构所施加的大小。在Python中,我们有任意精度的对象。对于较小的数字(那些适合32位的数字),我希望Perl更快。如果我们检查架构的整数大小,Perl脚本甚至在不进行某些修改的情况下也无法工作。
我在我的MacBookAir(32位)上使用我自己编译的Perl5.10.1和Leopard附带的python 2.5.1的原始基准测试中看到了类似的结果:
但是,我使用bignum向perl程序添加了任意精度
1 | use bignum; |
现在我想知道Perl版本是否会结束。:)完成后我会发布一些结果,但看起来会有一个数量级的差异。
你们中的一些人可能看到了我的问题,关于你最喜欢的语言,你最讨厌的五件事是什么?.perl的默认数字是我讨厌的事情之一。我不应该去想它,也不应该太慢。在Perl中,我两个都输了。但是,请注意,如果我需要在Perl中进行数字处理,我可以使用PDL。
is Python really that much slower than
Perl?
看看计算机语言基准游戏-"使用≈12个有缺陷的基准和≈1100个程序比较≈30种编程语言的性能"。
它们只是一个很小的基准测试程序,但它们仍然比您所计时的代码片段做得更多。-
http://shootout.alioth.debian.org/u32/python.php