Foo*_*baz 13 python perl performance
我已经是一个超过10年的Perl家伙,但是一位朋友说服我尝试使用Python并告诉我它比Perl快多少.所以只是为了踢,我把我用Perl编写的应用程序移植到Python中,发现它运行速度慢了3倍.最初,我的朋友告诉我,我一定做错了,所以我重写并重构,直到我不能重写和重构......它仍然慢得多.所以我做了一个简单的测试:
i = 0
j = 0
while (i < 100000000):
i = i + 1
j = j + 1
print j
Run Code Online (Sandbox Code Playgroud)
$ time python python.py
100000000真正的0m48.100s
用户0m45.633s
sys 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;
Run Code Online (Sandbox Code Playgroud)
$ time perl perl.pl
100000000实际0m24.757s
用户0m22.341s
sys 0m0.029s
慢了两倍,这似乎没有反映出我见过的任何基准测试......我的安装有问题还是Python真的比Perl慢得多?
Ben*_*kin 51
挑剔的答案是你应该将它与惯用的Python进行比较:
for循环(FlorianH的答案),与+=和xrange()取21. 摆脱j变量将其减少到8秒:
print sum(1 for i in xrange(100000000))
Python具有奇怪的属性,更高级别的更短代码往往是最快的:-)
但真正的答案是你的"微观基准"毫无意义.语言速度的真正问题是:平均实际应用程序的性能如何?要知道这一点,你应该考虑到:
复杂代码中典型的操作组合.您的代码不包含任何数据结构,函数调用或OOP操作.
足够大的代码库可以感受缓存效果 - 许多解释器优化会为了速度而交换内存,而任何微小的基准都无法公平地衡量.
优化 机会:在您编写代码后,如果速度不够快,您可以轻松实现多快?
例如,将繁重的工作卸载到有效的C libriries有多难?
PyPy的基准测试和Octane是现实语言速度基准测试的好例子.
如果你想谈论数字运算,Python的IS与科学家令人惊讶的流行.他们喜欢简单的伪数学语法和简短的学习曲线,但也喜欢用于数组运算的优秀numpy库以及包装其他现有C代码的简易性.
然后有Psyco JIT可能会在1秒内运行你的玩具示例,但我现在无法检查它,因为它只适用于32位x86.
编辑:现在,跳过Psyco并使用PyPy,这是一个跨平台积极改进JIT.
所有这些微观基准测试都会变得有点傻!
例如.只需for在Python和Perl中切换,就可以提供巨大的速度提升.如果使用原始Perl示例将快两倍for:
my $j = 0;
for my $i (1..100000000) {
++$j;
}
print $j;
Run Code Online (Sandbox Code Playgroud)
我可以用这个来削减一点:
++$j for 1..100000000;
print $j;
Run Code Online (Sandbox Code Playgroud)
变得更傻了我们可以把它降到1秒;-)
print {STDOUT} (1..10000000)[-1];
Run Code Online (Sandbox Code Playgroud)
/ I3az /
ref:使用Perl 5.10.1.
Python在数值计算方面并不是特别快,我确信它在文本处理方面比perl慢.
既然你是一个经验丰富的Perl手,我不知道这是否适用于你,但从长远来看Python程序往往更易于维护并且开发速度更快.对于大多数情况来说,速度"足够",当您真正需要提升性能时,您可以灵活地降低到C级.
好的.我刚刚创建了一个包含随机数据的大文件(1GB)(主要是ascii)并将其分成相等长度的行.这应该是模拟日志文件.
然后我运行简单的perl和python程序,逐行搜索文件以获得现有模式.
使用Python 2.6.2,结果是
real 0m18.364s
user 0m9.209s
sys 0m0.956s
Run Code Online (Sandbox Code Playgroud)
并使用Perl 5.10.0
real 0m17.639s
user 0m5.692s
sys 0m0.844s
Run Code Online (Sandbox Code Playgroud)
程序如下(如果我做了一些愚蠢的事,请告诉我)
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()
Run Code Online (Sandbox Code Playgroud)
和
sub search() {
open FOO,"/home/arif/f" or die $!;
while (<FOO>) {
print "Found : $_\n" if /p06c/o;
}
}
search();
Run Code Online (Sandbox Code Playgroud)
结果非常接近并以这种方式调整或其他似乎不会改变结果.我不知道这是否是一个真正的基准,但我认为这是我用两种语言搜索日志文件的方式,所以我对相对表现进行了纠正.
谢谢克里斯.
如果你使用python语言的正确语法,Python运行速度非常快.它大致被描述为" pythonic ".
如果像这样重构代码,它的运行速度至少要快两倍(好吧,它在我的机器上运行):
j = 0
for i in range(10000000):
j = j + 1
print j
Run Code Online (Sandbox Code Playgroud)
每当你在python中使用while时,你应该检查你是否也可以使用"for X in range()".
对于OP,在Python中这段代码:
j = 0
for i in range(10000000):
j = j + 1
print j
Run Code Online (Sandbox Code Playgroud)
是相同的
print range(10000001)[-1]
Run Code Online (Sandbox Code Playgroud)
在我的机器上,
$ time python test.py
10000000
real 0m1.138s
user 0m0.761s
sys 0m0.357s
Run Code Online (Sandbox Code Playgroud)
运行大约1秒.range()(或xrange)是Python的内部和"内部",它已经可以为你生成一系列数字.因此,您不必使用自己的循环创建自己的迭代.现在,你去找一个可以运行1秒的Perl等价物来产生相同的结果
Python 在字典中维护全局变量。因此,每次有赋值时,解释器都会在模块字典中执行查找,这有点昂贵,这就是您发现示例如此慢的原因。
为了提高性能,您应该使用本地分配,就像创建函数一样。Python解释器将局部变量存储在数组中,访问速度更快。
但是,应该注意的是,这是一个实现细节CPython的例如,我怀疑 IronPython 会导致完全不同的结果。
最后,有关此主题的更多信息,我建议您阅读 GvR 中有关 Python 优化的有趣文章:Python 模式 - 优化轶事。