为什么我的Python版本比Perl版本慢?

16 投票
9 回答
7575 浏览
提问于 2025-04-15 17:30

我用Perl已经超过10年了,但一个朋友让我试试Python,并告诉我Python比Perl快很多。于是我决定尝试一下,把我用Perl写的一个应用程序移植到Python上,结果发现它运行得慢了大约3倍。起初,我的朋友说我肯定是做错了,所以我不断重写和优化代码,直到我觉得没有什么可以再改的了……结果还是慢得多。于是我做了一个简单的测试:

i = 0
j = 0

while (i < 100000000):
    i = i + 1
    j = j + 1

print j

$ time python python.py
100000000

实际时间 0m48.100s
用户时间 0m45.633s
系统时间 0m0.043s

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

实际时间 0m24.757s
用户时间 0m22.341s
系统时间 0m0.029s

结果显示Python的速度几乎是Perl的两倍慢,这似乎和我看到的基准测试结果不太一致……难道是我的安装有问题,还是说Python真的比Perl慢这么多

9 个回答

8

如果你用对了Python的语法,Python运行得非常快。人们通常把这种写法称为“pythonic”。

如果你把代码调整成下面这样,它的运行速度至少会快一倍(在我的电脑上是这样的):

j = 0
for i in range(10000000):
    j = j + 1
print j

每次你在Python中使用while循环时,应该考虑一下是否可以用“for X in range()”来代替。

9

这些微基准测试有时候真让人觉得有点搞笑!

比如说,在Python和Perl中,换成用for循环就能让速度大幅提升。如果原来的Perl例子用for的话,速度会快一倍:

my $j = 0;

for my $i (1..100000000) {
    ++$j;
}

print $j;


而且我还可以通过这个方法再快一点:

++$j for 1..100000000;
print $j;


更搞笑的是,我们可以把时间缩短到1秒钟!;-)

print {STDOUT} (1..10000000)[-1];

/I3az/

参考: 使用的是Perl 5.10.1。

52

这里有一些关于代码性能的讨论:

  • 我在我的电脑上运行的原始代码需要34秒。

  • 使用一个 for 循环(参考 FlorianH的回答)和 += 以及 xrange() 的话,只需要21秒。

  • 把整个代码放进一个函数里,时间减少到9秒!
    这比Perl快多了(我电脑上Perl需要15秒)!
    解释一下: Python的局部变量比全局变量快得多
    (为了公平,我也试了在Perl中用函数 - 没有变化)

  • 去掉了j变量后,时间减少到8秒:

    print sum(1 for i in xrange(100000000))

Python有个奇怪的特点,就是更高层次、更简短的代码往往运行得更快 :-)

但真正的问题是,你的“微基准测试”其实没有意义。真正的语言速度问题是:一个普通的真实应用程序的性能如何?要了解这一点,你需要考虑:

  • 复杂代码中典型的操作组合。你的代码没有包含任何数据结构、函数调用或面向对象的操作。

  • 足够大的代码库来感受到缓存的效果——许多解释器优化是通过牺牲内存来换取速度,而这些在任何微小的基准测试中都无法公平测量。

  • 优化 机会:在你写完代码后,如果它不够快,你能轻松地让它快多少?

    比如,把重的计算任务交给高效的C库,难度有多大?

PyPy的基准测试Octane 是现实语言速度基准测试的好例子。

如果你想讨论数字运算,Python 确实 在科学家中非常受欢迎。他们喜欢它简单的伪数学语法和短的学习曲线,同时也喜欢优秀的 numpy 库来处理数组,以及轻松封装其他现有的C代码。

还有 Psyco JIT,它可能会让你的简单例子在1秒以内完成,但我现在无法检查,因为它只支持32位x86。
编辑:现在,建议跳过Psyco,使用 PyPy,这是一个跨平台的、正在积极改进的JIT。

撰写回答