[pyar] xrange (2.7) vs range(3.2)

Germán L. Osella Massa gosella en gmail.com
Jue Mayo 29 15:53:05 ART 2014


Interesante... ahora, ¿por qué pasa eso?

Analizando el código en Python, se ve que ambas versiones generan el mismo
bytecode:

$ python2
Python 2.7.6 (default, Feb 26 2014, 12:01:28)
[GCC 4.8.2 20140206 (prerelease)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> def func():
...   for i in xrange(1000000):
...      pass
...
>>> import dis
>>> dis.dis(func)
  2           0 SETUP_LOOP              20 (to 23)
              3 LOAD_GLOBAL              0 (xrange)
              6 LOAD_CONST               1 (1000000)
              9 CALL_FUNCTION            1
             12 GET_ITER
        >>   13 FOR_ITER                 6 (to 22)
             16 STORE_FAST               0 (i)

  3          19 JUMP_ABSOLUTE           13
        >>   22 POP_BLOCK
        >>   23 LOAD_CONST               0 (None)
             26 RETURN_VALUE
>>>

$ python
Python 3.4.1 (default, May 19 2014, 17:40:19)
[GCC 4.9.0 20140507 (prerelease)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> def func():
...    for i in range(1000000):
...       pass
...
>>> import dis
>>> dis.dis(func)
  2           0 SETUP_LOOP              20 (to 23)
              3 LOAD_GLOBAL              0 (range)
              6 LOAD_CONST               1 (1000000)
              9 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
             12 GET_ITER
        >>   13 FOR_ITER                 6 (to 22)
             16 STORE_FAST               0 (i)

  3          19 JUMP_ABSOLUTE           13
        >>   22 POP_BLOCK
        >>   23 LOAD_CONST               0 (None)
             26 RETURN_VALUE
>>>

El bytecode en ambas versiones el mismo...

Ahora, recuerdo que en Python 2.x, los enteros "pequeños" (menores a 2**31)
se representan como int mientras que los mayor a ese límite se representan
como long. En Python 3.x, ambos tipos se unificaron como el nuevo int, y
eso puede afectar los tiempos.

Viendo Objects/rangeobject.c en la rama de Python 2.7.6, uno se encuentra
que xrange usa un int para definir los rangos (por eso xrange(2**31) falla).

En cambio, en Objects/rangeobject.c de la rama de Python 3.4.1, en nuevo
range (que antes era xrange) trabaja con el nuevo int (que antes era long).

Comparando PyInt_FromLong de Objects/intobject.c de Python 2.7.6 (que es lo
que usa xrange) con PyLong_FromLong de Objects/longobject.c de Python 3.4.1
(que es lo que usan range) se puede ver que el segundo es mucho más
complejo que el primero y eso puede suma a la diferencia.

En mi netbook (con Python 2.7.6 y 3.4.1):

$ python2 -m timeit 'for i in xrange(1000000): pass'
10 loops, best of 3: 137 msec per loop

$ python -m timeit 'for i in range(1000000): pass'
10 loops, best of 3: 330 msec per loop

Ahora, ¿es culpa de range/xrange con los long/int o de la iteración en sí?
A ver...

$ python2 -m timeit -s 'lista = range(1000000)' 'for i in lista: pass'
10 loops, best of 3: 92.4 msec per loop

$ python -m timeit -s 'lista = list(range(1000000))' 'for i in lista: pass'
10 loops, best of 3: 112 msec per loop

La cosa mejora un poco pero puede verse que aún hay una diferencia entre
Python 2 y Python 3...

Habrá que ver que si hay alguna diferencia en las implementaciones de los
iteradores sobre listas o si se trata de algún cambio a nivel de la
interpretación de los bytecodes que causa la diferencia. Pero
lamentablemente ahora no puedo seguir viendo...

Sin embargo, antes de cerrar el mail, les comparto esto:

$ pypy -m timeit 'for i in xrange(1000000): pass'
100 loops, best of 3: 6.22 msec per loop

;-)



2014-05-29 8:47 GMT-03:00 Daniel <dmlistapython en gmail.com>:

>
> Hice la siguiente prueba:
>
> $ python -m timeit 'for i in xrange(1000000):' ' pass'
> 100 loops, best of 3: 18.4 msec per loop
>
> $ python3 -m timeit 'for i in range(1000000):' ' pass'
> 10 loops, best of 3: 31.3 msec per loop
>
> Por qué es más lento en python3 ¿no se supone que deberían comportase
> igual o estoy testeando mal?
>
>
>
> _______________________________________________
> pyar mailing list pyar en python.org.ar
> http://listas.python.org.ar/listinfo/pyar
>
> PyAr - Python Argentina - Sitio web: http://www.python.org.ar/
>
> La lista de PyAr esta Hosteada en USLA - Usuarios de Software Libre de
> Argentina - http://www.usla.org.ar
>
------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <http://listas.python.org.ar/pipermail/pyar/attachments/20140529/3681858f/attachment.html>


More information about the pyar mailing list