Почему Python 3 значительно медленнее, чем Python 2? [Дубликат]
На этот вопрос уже есть ответ здесь:
Есть ли причина, по которой Python 3 перечисляет медленнее, чем Python 2? 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 bit
машина с2.6Ghz
процессор и рассчитал время с помощьюtime.time()
в одном цикле.
Output : Python 3.4
-----------------
2.6392083168029785
0.9724123477935791
Output: Python 2.7
------------------
1.5131521225
0.475143909454
Я действительно не думаю, что были внесены изменения в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
А ниже - разобранный байт-код для функции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 действительно вызывает такое огромное изменение времени выполнения в данном фрагменте кода.