关于性能:为什么我的Python版本比我的Perl版本慢?

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
100000000

real 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
100000000

real 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中只需切换到for,就会大大提高速度。如果使用for,原始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