为什么python与Ruby相比速度较慢,即使使用了这个非常简单的;测试;?

为什么python与Ruby相比速度较慢,即使使用了这个非常简单的;测试;?,python,ruby,testing,performance,Python,Ruby,Testing,Performance,请参阅,以了解我之前理解python和ruby之间差异的尝试 正如igouy所指出的,我提出的python变慢的原因可能不是递归函数调用(涉及堆栈) 我做的 #!/usr/bin/python2.7 i = 0 a = 0 while i < 6553500: i += 1 if i != 6553500: a = i else: print "o" print a #/usr/bin/python2.7 i=0 a=0 当我

请参阅,以了解我之前理解python和ruby之间差异的尝试

正如igouy所指出的,我提出的python变慢的原因可能不是递归函数调用(涉及堆栈)

我做的

#!/usr/bin/python2.7
i = 0
a = 0
while i < 6553500:
    i += 1
    if i != 6553500:
       a = i 
    else:
        print "o" 
print a 
#/usr/bin/python2.7
i=0
a=0
当我<6553500时:
i+=1
如果我6553500:
a=i
其他:
打印“o”
打印
在ruby中是

#!/usr/bin/ruby
i = 0
a = 0
while i < 6553500
    i += 1
    if i != 6553500
       a = i 
    else
        print "o"
    end
end   
print a
#/usr/bin/ruby
i=0
a=0
而我<6553500
i+=1
如果我6553500
a=i
其他的
打印“o”
结束
结束
打印
Python 3.1.2(r312:79147,2010年10月4日,12:45:09) [GCC 4.5.1]关于linux2

时间python pytest.py o

6553499

实际0m3.637s

用户0m3.586s

ruby 1.9.2p0(2010-08-18修订版29036)[x86_64-linux] time ruby rutest.rb

o6553499

实际0.618s

用户0.610s

让它循环得越高,差异就越大。添加额外的0,ruby在7秒内完成,而python运行40秒

这是在Intel(R)Core(TM)i7 CPU M 620@2.67GHz和4GB内存上运行的


为什么会这样?

这太简单了。也许在这种情况下,Ruby会更快。但是,当您需要处理更复杂的数据类型及其方法时,Python会发挥优势。Python实现了更多的“实现方法”,您必须选择一种最简单且足够的方法。Ruby使用更抽象的实体,需要的知识更少。但是,当Python中的同一个任务能够实现时,深入阅读手册,找到越来越多的类型和方法/函数组合,经过一段时间后,就有可能生成比Ruby快得多的程序

如果您只想得到结果,而不是性能,那么Ruby更简单、更易于编写。但是,任务越复杂,经过数小时的优化后,Python在性能方面的优势就越大


UPD:虽然Ruby和Python有很多共同点,但性能和高级别将具有相反的比例。

首先,请注意,您展示的Python版本是不正确的:您在Python2.7而不是3.1中运行此代码(它甚至不是有效的Python3代码)。(仅供参考,Python 3通常比2慢。)

这就是说,Python测试中存在一个关键问题:您将其作为全局代码编写。你需要把它写成一个函数。在Python2和Python3中正确编写时,它的运行速度大约是原来的两倍:

def main():
    i = 0
    a = 0
    while i < 6553500:
        i += 1
        if i != 6553500:
           a = i
        else:
            print("o")
    print(a)

if __name__ == "__main__":
    main()
def main():
i=0
a=0
当我<6553500时:
i+=1
如果我6553500:
a=i
其他:
打印(“o”)
印刷品(a)
如果名称=“\uuuuu main\uuuuuuuu”:
main()
当您全局编写代码时,您没有本地代码;所有变量都是全局变量。在Python中,局部变量比全局变量快得多,因为全局变量存储在
dict
中。VM可以通过索引直接引用局部变量,因此不需要哈希表查找

另外,请注意,这是一个非常简单的测试,您真正做的是对一些任意字节码操作进行基准测试。

在我朋友的笔记本电脑(Windows7 64位,python 2.6,3GB RAM)上,python对6553500的输入只需约1秒,对65535000的输入只需10秒。我想知道你的电脑为什么花这么多时间。当我改用xrange和局部变量时,它还减少了一些较大输入的时间

我不能评论Ruby,因为它没有安装在这台计算机上

为什么会这样

Python的循环(for,while)对于处理动态类型来说并不快。在这种情况下,它将失去优势

但是cython成了救世主
下面的纯python版本借用了Glenn Maynard的答案(未打印)
cython版本非常简单,基于此,对于新的python程序员来说,它非常简单,可以阅读:

def main():
    cdef int i = 0
    cdef int a = 0
    while i < 6553500:
        i += 1
        if i != 6553500:
            a = i
        else:
            pass  # print "0"
    return a

if __name__ == "__main__":
    print main()
更新:正如Glenn Maynard在评论中指出的,而i 我测试xrange的实现。
py与Glenn Maynard的verison相同。foo.py的代码是:

def main():
    for i in xrange(6553500):
        pass
    a = i
    return a

if __name__ == "__main__":
    print main()
~/code/note$ time python2.7 spam.py  # Glenn Maynard's while version
6553499

real    0m2.128s
user    0m2.080s
sys     0m0.044s
:~/code/note$ time python2.7 foo.py  # xrange version, as Glenn Maynard point out in comment
6553499

real    0m0.618s
user    0m0.604s
sys     0m0.016s

此外,Python中的全局变量速度较慢。如果你把相同的代码放在一个函数中并调用该函数,速度会快得多。我不是想得出哪种语言“更好”或我应该使用哪种语言的指南,只是对这一点的解释,以及(上面的程序)在速度上的差异。我不在乎每种语言是什么或不是什么,也不在乎它应该怎么做。我只是想知道,对于一个在两种语言中看起来完全相同的非常简单的程序来说,什么会影响速度上的巨大差异@Thomas,我把它移到了一个函数,还是一样的。我开始解释这个答案没有意义的地方,然后发现这个答案中几乎每个句子都是胡说八道,所以我放弃了……代码看起来可能“完全一样”,但因为语言事实上非常不同,它们实际上并不相同。语义是不同的,即使您在代码中没有注意到,因为您只依赖语义的一小部分。至于将其放入函数中,请参见Glenn Maynard的回答。@AntonioP,正如我在开始时所说,这是一个太简单的测试。它不是一个ASM,编译后这个程序将有很多页的机器代码,这些代码被数百种不同的优化(对于不同的语言来说确实不同)处理。如果你能查看它的机器代码,你永远不会认为它是同一个程序)Python也是在64位模式下编译的吗?@Mark Rushakoff,它在这个测试中会有帮助吗?@Mark,是的/usr/bin/python2.7:ELF 64位LSB可执行文件,x86-64,版本1(SYSV),动态链接(使用共享libs),对于GNU/Linux 2.6.18,Python还可以优化(-O选项)。我很想知道这是否会对您的测试产生影响。@Jason:
-O
什么都不做,因为它只会剥离断言。优化动态语言很难,而且很少有人
def main():
    for i in xrange(6553500):
        pass
    a = i
    return a

if __name__ == "__main__":
    print main()
~/code/note$ time python2.7 spam.py  # Glenn Maynard's while version
6553499

real    0m2.128s
user    0m2.080s
sys     0m0.044s
:~/code/note$ time python2.7 foo.py  # xrange version, as Glenn Maynard point out in comment
6553499

real    0m0.618s
user    0m0.604s
sys     0m0.016s