gsb*_*eng 36 python performance cpython python-2.7 python-3.x
我一直试图理解为什么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
Run Code Online (Sandbox Code Playgroud)
当我尝试用py3.4和py2.7运行这个程序时,我得到了以下结果.
注意:这些统计数据来自64 bit具有2.6Ghz处理器的计算机,并使用time.time()单循环计算时间.
Output : Python 3.4
-----------------
2.6392083168029785
0.9724123477935791
Output: Python 2.7
------------------
1.5131521225
0.475143909454
Run Code Online (Sandbox Code Playgroud)
我真的不认为出现了适用于变更while或xrange从2.7到3.4,我知道range已经开始作为对xrange在py3.4但文件说,
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
Run Code Online (Sandbox Code Playgroud)
以下是函数的反汇编字节代码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
Run Code Online (Sandbox Code Playgroud)
如果我们比较两个字节代码,它们就会产生相同的反汇编字节代码.
现在我想知道从2.7到3.4的变化是否真正导致给定代码段中执行时间的这一巨大变化.
Mar*_*ers 34
不同之处在于int类型的实现.蟒3.X使用任意大小的整数类型(long在2.X)排他地,而在Python x为值高达sys.maxint更简单的int类型被用于使用一个简单的C long引擎盖下.
一旦将循环限制为long整数,Python 3.x就会更快:
>>> from timeit import timeit
>>> MAX_NUM = 3*10**3
>>> def bar():
... i = MAX_NUM + sys.maxsize
... while i > sys.maxsize:
... i -= 1
...
Run Code Online (Sandbox Code Playgroud)
Python 2:
>>> timeit(bar, number=10000)
5.704327821731567
Run Code Online (Sandbox Code Playgroud)
Python 3:
>>> timeit(bar, number=10000)
3.7299320790334605
Run Code Online (Sandbox Code Playgroud)
我用sys.maxsize作为sys.maxint从Python 3的下降,但整数值基本相同.
因此,Python 2中的速度差异仅限于64位上的第一个(2**63)-1个整数,(2**31) - 32位系统上的1个整数.
由于您无法在Python 2上使用该long类型xrange(),因此我没有包含该函数的比较.
| 归档时间: |
|
| 查看次数: |
15972 次 |
| 最近记录: |