See Is there something wrong with this python code, why does it run so slow compared to ruby? for my previous attempt at understanding the differences between python and ruby.
As pointed out by igouy the reasoning I came up with for python being slower could be something else than due to recursive function calls (stack involved).
I made this
#!/usr/bin/python2.7
i = 0
a = 0
while i < 6553500:
i += 1
if i != 6553500:
a = i
else:
print "o"
print a
In ruby it is
#!/usr/bin/ruby
i = 0
a = 0
while i < 6553500
i += 1
if i != 6553500
a = i
else
print "o"
end
end
print a
Python 3.1.2 (r312:79147, Oct 4 2010, 12:45:09) [GCC 4.5.1] on linux2
time python pytest.py o
6553499
real 0m3.637s
user 0m3.586s
ruby 1.9.2p0 (2010-08-18 revision 29036开发者_JS百科) [x86_64-linux] time ruby rutest.rb
o6553499
real 0m0.618s
user 0m0.610s
Letting it loop higher gives higher differences. Adding an extra 0, ruby finishes in 7s, while python runs for 40s.
This is run on Intel(R) Core(TM) i7 CPU M 620 @ 2.67GHz with 4GB mem.
Why is this so?
First off, note that the Python version you show is incorrect: you're running this code in Python 2.7, not 3.1 (it's not even valid Python3 code). (FYI, Python 3 is usually slower than 2.)
That said, there's a critical problem in the Python test: you're writing it as global code. You need to write it as a function. It runs about twice as fast when written correctly, in both Python 2 and 3:
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()
When you write code globally, you have no locals; all of your variables are global variables. Locals are much faster than globals in Python, because globals are stored in a dict
. Locals can be referenced directly by the VM by index, so no hash table lookups are needed.
Also, note that this is such a simple test, what you're really doing is benchmarking a few arbitrary bytecode operations.
Why is this so?
Python's loop (for, while) isn't fast for handle dynamic types. in such a case, it lose the advantage.
but cython becames the salvation
pure python version below borrowed from Glenn Maynard's answer (without print)
cython version is very easy based on this, it's is easy enough for a new python programmer can read :
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()
on my pc, python version need 2.5s, cython version need 5.5ms:
In [1]: import pyximport
In [2]: pyximport.install()
In [3]: import spam # pure python version
In [4]: timeit spam.main()
1 loops, best of 3: 2.41 s per loop
In [5]: import eggs # cython version
In [6]: timeit eggs.main()
100 loops, best of 3: 5.51 ms per loop
update: as Glenn Maynard point out in the comment, while i < N: i+= 1 is not pythonic.
I test xrange implementation.
spam.py is the same as Glenn Maynard's verison. foo.py's code is:
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
On my friend's laptop (Windows7 64 bit, python 2.6, 3GB RAM), python takes only around 1 sec for 6553500 and 10 secs for 65535000 input. I wonder why your computer is taking so much time. It also shaves off some time on the larger input when I use xrange and local variables instead.
I cannot comment on Ruby since it's not installed on this computer.
It's too simple test. Maybe in such things Ruby is faster. But Python takes advantage, when you need to work with more complex datatypes and their methods. Python have much more implemented "ways to do this", and you must choose the one, which is the simplest and enough. Ruby works with more abstract entities and it requires less knowledge. But when it is possible in the same task in Python go deeper in it's manuals and find more and more combinations of types and methods/functions, it is possible after time to make much more faster program, than Ruby.
Ruby is simplier and easier to write, if you just want to get result, not perfomance. But the more complex you task is, the more advantage Python will have in perfomance after hours of optimizing.
UPD: While Ruby and Python have so much common things, the perfomace and high-levelness will have the reverse proportionality.
精彩评论