Estoy optimizando algún código cuyo cuello de botella principal se está ejecutando y accediendo a una lista muy grande de objetos similares a estructuras. Actualmente estoy usando namedtuples, para la legibilidad. Sin embargo, algunos de evaluación comparativa rápida usando 'timeit' muestra que este es realmente el camino equivocado donde el rendimiento es un factor:¿Cuál es el objeto similar a una estructura más rápido (de acceso) en Python?
tupla nombre con a, b, c:
>>> timeit("z = a.c", "from __main__ import a")
0.38655471766332994
Clase usando __slots__
, con una , b, c:
>>> timeit("z = b.c", "from __main__ import b")
0.14527461047146062
diccionario con claves a, b, c:
>>> timeit("z = c['c']", "from __main__ import c")
0.11588272541098377
Tupla con tres valores, utilizando una clave constante:
>>> timeit("z = d[2]", "from __main__ import d")
0.11106188992948773
lista con tres valores, utilizando una clave constante:
>>> timeit("z = e[2]", "from __main__ import e")
0.086038238242508669
tupla con tres valores, utilizando una clave local:
>>> timeit("z = d[key]", "from __main__ import d, key")
0.11187358437882722
Lista con tres valores, usando una clave local:
>>> timeit("z = e[key]", "from __main__ import e, key")
0.088604143037173344
En primer lugar, ¿hay algo acerca de estas pequeñas pruebas timeit
que las invalidaría? Corrí varias veces para asegurarme de que ningún evento aleatorio del sistema los hubiera descartado, y los resultados fueron casi idénticos.
Parece que los diccionarios ofrecen el mejor equilibrio entre el rendimiento y la legibilidad, con las clases en segundo lugar. Esto es desafortunado, ya que, para mi propósito, también necesito que el objeto sea similar a una secuencia; de ahí mi elección de namedtuple.
Las listas son sustancialmente más rápidas, pero las claves constantes no se pueden mantener; Tendría que crear un conjunto de constantes de índice, es decir, KEY_1 = 1, KEY_2 = 2, etc. que tampoco es ideal.
¿Estoy atascado con estas opciones, o hay una alternativa que me he perdido?
Si el rendimiento es una prioridad, ¿por qué no utilizar C? – Skilldrick
@Skilldrick: esta es solo una pequeña parte de un programa más grande, que se beneficia al estar escrito en Python. Volver a escribir esta parte como una extensión C es una opción, pero algo indeseable, ya que el otro código también afecta los datos, complicando un poco las cosas. El rendimiento es importante, pero no * tan * crucial; Estaría muy contento con la mejora 4x ofrecida por las listas, si no fuera por el mantenimiento reducido. Solo estoy buscando otras opciones antes de decidir qué camino tomar. – DNS
@Warren P: Sí; No estoy optimizando prematuramente. Este es un ciclo muy cerrado en el que simplemente acceder a las estructuras es una fracción significativa del trabajo. Es el ciclo restante más lento en el programa. Incluso una mejora modesta podría reducir uno o dos segundos el tiempo de ejecución del mundo real. Como todo se repite, eso se suma. – DNS