为什么Python 3比Python 2慢很多? [英] Why is Python 3 is considerably slower than Python 2?
问题描述
我一直试图理解为什么在某些情况下Python 3与Python 2相比实际上要花费很多时间,以下是我从python 3.4到python 2.7进行验证的几种情况。
I've been trying to understand why Python 3 is actually taking much time compared with Python 2 in certain situations, below are few cases I've verified from python 3.4 to python 2.7.
注意:我已经经历过一些问题,例如为什么Python3中没有xrange函数?和在python3中循环比python2慢得多和相同的代码与Python2相比,Python3的速度要慢一些,但是我觉得我没有得到这个问题的真正原因。
Note: I've gone through some of the questions like Why is there no xrange function in Python3? and loop in python3 much slower than python2 and Same code slower in Python3 as compared to Python2, but I feel that I didn't get the actual reason behind this issue.
我已经尝试过代码来显示它如何发挥作用:
I've tried this piece of code to show how it is making difference:
MAX_NUM = 3*10**7
# This is to make compatible with py3.4.
try:
xrange
except:
xrange = range
def foo():
i = MAX_NUM
while i> 0:
i -= 1
def foo_for():
for i in xrange(MAX_NUM):
pass
当我尝试使用py3.4和py2.7运行该程序时,我得到的结果低于
。
When I've tried running this programme with py3.4 and py2.7 I've got below results.
注意:这些统计信息来自具有 2.6Ghz
处理器的 64位
计算机并在单个循环中使用 time.time()
计算时间。
Note: These stats came through a 64 bit
machine with 2.6Ghz
processor and calculated the time using time.time()
in single loop.
Output : Python 3.4
-----------------
2.6392083168029785
0.9724123477935791
Output: Python 2.7
------------------
1.5131521225
0.475143909454
我真的不认为对 c或
xrange
从2.7到3.4,我知道 range
在py3.4中已经开始充当 xrange
的角色,但正如文档所述
I really don't think that there has been changes applied to while
or xrange
from 2.7 to 3.4, I know range
has been started acting as to xrange
in py3.4 but as documentation says
range()
现在的行为类似于xrange()
以前的行为是xcept可与任意大小的值一起使用。后者不再存在。
range()
now behaves likexrange()
used to behave, except it works with values of arbitrary size. The latter no longer exists.
这意味着从 xrange
更改为 range
非常类似于更改名称,但是可以使用任意值。
this means change from xrange
to range
is very much equal to a name change but working with arbitrary values.
我也验证了反汇编的字节码
I've verified disassembled byte code as well.
下面是函数 foo()
的反汇编字节码:
Below is the disassembled byte code for function foo()
:
Python 3.4:
---------------
13 0 LOAD_GLOBAL 0 (MAX_NUM)
3 STORE_FAST 0 (i)
14 6 SETUP_LOOP 26 (to 35)
>> 9 LOAD_FAST 0 (i)
12 LOAD_CONST 1 (0)
15 COMPARE_OP 4 (>)
18 POP_JUMP_IF_FALSE 34
15 21 LOAD_FAST 0 (i)
24 LOAD_CONST 2 (1)
27 INPLACE_SUBTRACT
28 STORE_FAST 0 (i)
31 JUMP_ABSOLUTE 9
>> 34 POP_BLOCK
>> 35 LOAD_CONST 0 (None)
38 RETURN_VALUE
python 2.7
-------------
13 0 LOAD_GLOBAL 0 (MAX_NUM)
3 STORE_FAST 0 (i)
14 6 SETUP_LOOP 26 (to 35)
>> 9 LOAD_FAST 0 (i)
12 LOAD_CONST 1 (0)
15 COMPARE_OP 4 (>)
18 POP_JUMP_IF_FALSE 34
15 21 LOAD_FAST 0 (i)
24 LOAD_CONST 2 (1)
27 INPLACE_SUBTRACT
28 STORE_FAST 0 (i)
31 JUMP_ABSOLUTE 9
>> 34 POP_BLOCK
>> 35 LOAD_CONST 0 (None)
38 RETURN_VALUE
下面是该函数的反汇编字节码 foo_for()
:
And below is the disassembled byte code for function foo_for()
:
Python: 3.4
19 0 SETUP_LOOP 20 (to 23)
3 LOAD_GLOBAL 0 (xrange)
6 LOAD_GLOBAL 1 (MAX_NUM)
9 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
12 GET_ITER
>> 13 FOR_ITER 6 (to 22)
16 STORE_FAST 0 (i)
20 19 JUMP_ABSOLUTE 13
>> 22 POP_BLOCK
>> 23 LOAD_CONST 0 (None)
26 RETURN_VALUE
Python: 2.7
-------------
19 0 SETUP_LOOP 20 (to 23)
3 LOAD_GLOBAL 0 (xrange)
6 LOAD_GLOBAL 1 (MAX_NUM)
9 CALL_FUNCTION 1
12 GET_ITER
>> 13 FOR_ITER 6 (to 22)
16 STORE_FAST 0 (i)
20 19 JUMP_ABSOLUTE 13
>> 22 POP_BLOCK
>> 23 LOAD_CONST 0 (None)
26 RETURN_VALUE
如果我们比较两个字节码,它们
If we compare both the byte codes they've produced the same disassembled byte code.
现在,我想知道从2.7到3.4的什么变化确实会导致给定代码段执行时间的巨大变化。
Now I'm wondering what change from 2.7 to 3.4 is really causing this huge change in execution time in the given piece of code.
推荐答案
不同之处在于 int
类型的实现。 Python 3.x仅使用任意大小的整数类型(在2.x中为 long
),而在Python 2.x中,其值最高为 sys .maxint
使用更简单的 int
类型,该类型在引擎盖下使用简单的C long
The difference is in the implementation of the int
type. Python 3.x uses the arbitrary-sized integer type (long
in 2.x) exclusively, while in Python 2.x for values up to sys.maxint
a simpler int
type is used that uses a simple C long
under the hood.
一旦将循环限制为 long
个整数,Python 3.x是更快:
Once you limit your loops to long
integers, Python 3.x is faster:
>>> from timeit import timeit
>>> MAX_NUM = 3*10**3
>>> def bar():
... i = MAX_NUM + sys.maxsize
... while i > sys.maxsize:
... i -= 1
...
Python 2:
>>> timeit(bar, number=10000)
5.704327821731567
Python 3:
>>> timeit(bar, number=10000)
3.7299320790334605
我用过 sys.maxsize
作为 sys.maxint
从Python 3中删除的,但整数值基本相同。
I used sys.maxsize
as sys.maxint
was dropped from Python 3, but the integer value is basically the same.
因此,Python 2的速度差异仅限于第一个(2 ** 63)-64位为1个整数,(2 ** 31)-32位系统为1个整数。
The speed difference in Python 2 is thus limited to the first (2 ** 63) - 1 integers on 64-bit, (2 ** 31) - 1 integers on 32 bit systems.
由于不能在 xrange()
上使用 long
类型Python 2,我没有对该函数进行比较。
Since you cannot use the long
type with xrange()
on Python 2, I did not include a comparison for that function.
这篇关于为什么Python 3比Python 2慢很多?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!