为什么Python 3比Python 2慢得多?

15 浏览
0 Comments

为什么Python 3比Python 2慢得多?

我一直在努力理解为什么在某些情况下,Python 3与Python 2相比需要更长的时间。以下是我从Python 3.4到Python 2.7验证的一些情况。

注意:我已经阅读了一些类似为什么Python3没有xrange函数?Python3中的循环比Python2慢得多相同的代码在Python3中比Python2慢的问题,但我感觉我没有得到这个问题背后的真正原因。

我尝试了下面这段代码来展示它是如何产生差异的:

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运行这个程序时,我得到了以下结果。

注意:这些统计数据是通过一个64位机器和2.6Ghz处理器计算的,在单个循环中使用time.time()计算时间。

输出:Python 3.4

-----------------

2.6392083168029785

0.9724123477935791

输出:Python 2.7

------------------

1.5131521225

0.475143909454

我真的不认为在2.7到3.4之间对while或xrange进行了改变,我知道在py3.4中,range开始像xrange一样工作,但正如文档所说的:

range()现在的行为类似于xrange()的行为,只是它可以使用任意大小的值。后者不再存在。

这意味着从xrange到range的改变与名称更改相当,但可以使用任意值。

我也验证了反汇编的字节码。

下面是函数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()的反汇编字节码:

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

如果我们比较这两个字节码,它们产生了相同的反汇编字节码。

现在我想知道从2.7到3.4的变化是真正导致了这段给定代码执行时间巨大变化的原因。

0