¿Por qué Python 3 es considerablemente más lento que Python 2? [duplicar]
Esta pregunta ya tiene una respuesta aquí:
He estado tratando de entender por qué Python 3 realmente está tomando mucho tiempo en comparación con Python 2 en ciertas situaciones, a continuación se muestran algunos casos que he verificado de python 3.4 a python 2.7.
Nota: He ido a través de algunas de las preguntas como ¿Por qué no hay ninguna función xrange en Python3? y bucle en python3 mucho más lento que python2 y Mismo código más lento en Python3 en comparación con Python2, pero siento que no entiendo la razón real detrás de este problema.
He probado este fragmento de código para mostrar cómo está haciendo la diferencia:
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
Cuando he intentado ejecutar este programa con py3. 4 y py2. 7 tengo a continuación resultado.
Nota: Estos las estadísticas llegaron a través de una máquina 64 bit
con procesador 2.6Ghz
y calcularon el tiempo usando time.time()
en bucle único.
Output : Python 3.4
-----------------
2.6392083168029785
0.9724123477935791
Output: Python 2.7
------------------
1.5131521225
0.475143909454
Realmente no creo que haya habido cambios aplicados a while
o xrange
de 2.7 a 3.4, sé que range
se ha comenzado a actuar como a xrange
en py3. 4 pero como dice la documentación{[18]]}
range()
ahora se comporta comoxrange()
solía comportarse, excepto que funciona con valores de tamaño arbitrario. Ya no existe.
Esto significa un cambio de xrange
a range
es muy igual a un cambio de nombre pero trabajando con valores arbitrarios.
También he verificado el código de bytes desmontado.
A continuación se muestra el código de bytes desmontado para la función 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
Y debajo está el código de bytes desmontado para la función 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
Si comparamos ambos códigos de bytes, han producido el mismo código de bytes desmontado.
Ahora me pregunto qué cambio de 2.7 a 3.4 está causando realmente este gran cambio en el tiempo de ejecución en la pieza de código.
1 answers
La diferencia está en la implementación del tipo int
. Python 3.x utiliza el tipo entero de tamaño arbitrario (long
en 2.x) exclusivamente, mientras que en Python 2.x para valores hasta sys.maxint
se usa un tipo int
más simple que usa un C long
simple debajo del capó.
Una vez que limite sus bucles a long
enteros, Python 3.x es más rápido:
>>> from timeit import timeit
>>> MAX_NUM = 3*10**3
>>> def bar():
... i = MAX_NUM + sys.maxsize
... while i > sys.maxsize:
... i -= 1
...
Python 2: {[14]]}
>>> timeit(bar, number=10000)
5.704327821731567
Python 3: {[14]]}
>>> timeit(bar, number=10000)
3.7299320790334605
Usé sys.maxsize
ya que sys.maxint
se eliminó de Python 3, pero el entero valor es básicamente el mismo.
La diferencia de velocidad en Python 2 se limita a los primeros (2 ** 63) - 1 enteros en 64 bits, (2 ** 31)-1 enteros en sistemas de 32 bits.
Dado que no puede usar el tipo long
con xrange()
en Python 2, no incluí una comparación para esa función.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-21 20:37:07