Algunos puntos base:
- Las llamadas al método Python son "caras" debido a su naturaleza interpretada . En teoría, si su código es lo suficientemente simple, desglosar el código de Python tiene un impacto negativo además de la legibilidad y la reutilización ( que es una gran ganancia para los desarrolladores, no tanto para los usuarios ).
- El principio de responsabilidad única (SRP) mantiene el código legible, es más fácil de probar y mantener.
- El proyecto tiene un tipo especial de antecedentes donde queremos código legible, pruebas y rendimiento de tiempo.
Por ejemplo, un código como este que invoca varios métodos (x4) es más lento que el siguiente, que es solo uno.
from operator import add
class Vector:
def __init__(self,list_of_3):
self.coordinates = list_of_3
def move(self,movement):
self.coordinates = list( map(add, self.coordinates, movement))
return self.coordinates
def revert(self):
self.coordinates = self.coordinates[::-1]
return self.coordinates
def get_coordinates(self):
return self.coordinates
## Operation with one vector
vec3 = Vector([1,2,3])
vec3.move([1,1,1])
vec3.revert()
vec3.get_coordinates()
En comparación con esto:
from operator import add
def move_and_revert_and_return(vector,movement):
return list( map(add, vector, movement) )[::-1]
move_and_revert_and_return([1,2,3],[1,1,1])
Si tengo que paralelizar algo como eso, es bastante objetivo que pierda rendimiento. Eso sí que es solo un ejemplo; mi proyecto tiene varias mini rutinas con matemáticas como esa: aunque es mucho más fácil trabajar con ellas, a nuestros perfiladores no les gusta.
¿Cómo y dónde adoptamos el SRP sin comprometer el rendimiento en Python, ya que su implementación inherente lo afecta directamente?
¿Existen soluciones alternativas, como algún tipo de preprocesador que ponga las cosas en línea para su lanzamiento?
¿O es Python simplemente pobre en el manejo del desglose del código por completo?
python
performance
single-responsibility
methods
lucasgcb
fuente
fuente
Respuestas:
Desafortunadamente sí, Python es lento y hay muchas anécdotas sobre personas que aumentan drásticamente el rendimiento al incorporar funciones y hacer que su código sea feo.
Hay una solución alternativa, Cython, que es una versión compilada de Python y mucho más rápida.
--Edite Solo quería abordar algunos de los comentarios y otras respuestas. Aunque el empuje de ellos no es quizás específico de Python. pero una optimización más general.
No optimice hasta que tenga un problema y luego busque cuellos de botella
En general un buen consejo. Pero la suposición es que el código 'normal' suele ser eficaz. Este no es siempre el caso. Los lenguajes y marcos individuales tienen sus propias idiosincrasias. En este caso, la función llama.
Son solo unos pocos milisegundos, otras cosas serán más lentas
Si está ejecutando su código en una computadora de escritorio potente, probablemente no le importe mientras su código de usuario único se ejecute en unos segundos.
Pero el código comercial tiende a ejecutarse para múltiples usuarios y requiere más de una máquina para soportar la carga. Si su código se ejecuta el doble de rápido, significa que puede tener el doble de usuarios o la mitad de máquinas.
Si posee sus máquinas y su centro de datos, generalmente tiene una gran cantidad de sobrecarga en la potencia de la CPU. Si su código funciona un poco lento, puede absorberlo, al menos hasta que necesite comprar una segunda máquina.
En estos días de computación en la nube, donde solo usa exactamente la potencia de cómputo que necesita y no más, hay un costo directo para el código que no funciona.
Mejorar el rendimiento puede reducir drásticamente el gasto principal para un negocio basado en la nube y el rendimiento realmente debería ser el centro y la delantera.
fuente
Muchas posibles preocupaciones de rendimiento no son realmente un problema en la práctica. El problema que plantea puede ser uno de ellos. En la lengua vernácula, llamamos preocuparse por esos problemas sin probar que son problemas reales de optimización prematura.
Si está escribiendo un front-end para un servicio web, su rendimiento no se verá afectado significativamente por las llamadas a funciones, ya que el costo de enviar datos a través de una red supera con creces el tiempo que lleva realizar una llamada al método.
Si está escribiendo un ciclo cerrado que actualiza una pantalla de video sesenta veces por segundo, entonces podría ser importante. Pero en ese momento, afirmo que tiene problemas más grandes si está tratando de usar Python para hacer eso, un trabajo para el cual Python probablemente no sea adecuado.
Como siempre, la forma de averiguarlo es medir. Ejecute un perfilador de rendimiento o algunos temporizadores sobre su código. Vea si es un problema real en la práctica.
El principio de responsabilidad única no es una ley o mandato; Es una directriz o principio. El diseño de software siempre se trata de compensaciones; No hay absolutos. No es raro intercambiar legibilidad y / o facilidad de mantenimiento por la velocidad, por lo que es posible que tenga que sacrificar SRP en el altar del rendimiento. Pero no haga esa compensación a menos que sepa que tiene un problema de rendimiento.
fuente
Primero, algunas aclaraciones: Python es un lenguaje. Hay varios intérpretes diferentes que pueden ejecutar código escrito en el lenguaje Python. La implementación de referencia (CPython) suele ser a lo que se hace referencia cuando alguien habla de "Python" como si fuera una implementación, pero es importante ser preciso al hablar de las características de rendimiento, ya que pueden diferir enormemente entre implementaciones.
Caso 1.) Si tiene código Python puro (<= Python Language versión 3.5, 3.6 tiene "soporte de nivel beta") que solo se basa en módulos Python puros, puede adoptar SRP en todas partes y usar PyPy para ejecutarlo. PyPy ( https://morepypy.blogspot.com/2019/03/pypy-v71-released-now-uses-utf-8.html ) es un intérprete de Python que tiene un compilador Just in Time (JIT) y puede eliminar la función llamar a gastos generales siempre que tenga tiempo suficiente para "calentarse" rastreando el código ejecutado (unos segundos IIRC). ** **
Si está restringido a usar el intérprete CPython, puede extraer las funciones lentas en extensiones escritas en C, que se precompilarán y no sufrirán ninguna sobrecarga del intérprete. Todavía puede usar SRP en todas partes, pero su código se dividirá entre Python y C. Si esto es mejor o peor para la mantenibilidad que abandonar selectivamente SRP pero apegarse solo al código Python depende de su equipo, pero si tiene secciones críticas de rendimiento de su código, sin duda será más rápido que incluso el código Python puro más optimizado interpretado por CPython. Muchas de las bibliotecas matemáticas más rápidas de Python utilizan este método (IIRC numpy y scipy). Lo cual es un buen ejemplo del caso 2 ...
Caso 2.) Si tiene código Python que usa extensiones C (o se basa en bibliotecas que usan extensiones C), PyPy puede o no ser útil dependiendo de cómo estén escritas. Consulte http://doc.pypy.org/en/latest/extending.html para obtener detalles, pero el resumen es que CFFI tiene una sobrecarga mínima mientras que CTypes es más lento (usarlo con PyPy puede ser incluso más lento que CPython)
Cython ( https://cython.org/ ) es otra opción con la que no tengo tanta experiencia. Lo menciono por completo para que mi respuesta pueda "sostenerse por sí misma", pero no reclame ninguna experiencia. Debido a mi uso limitado, sentí que tenía que trabajar más para obtener las mismas mejoras de velocidad que podía obtener "gratis" con PyPy, y si necesitaba algo mejor que PyPy, era igual de fácil escribir mi propia extensión C ( lo que tiene la ventaja si reutilizo el código en otro lugar o extraigo parte de él en una biblioteca, todo mi código aún puede ejecutarse con cualquier intérprete de Python y no es necesario que Cython lo ejecute).
Tengo miedo de estar "encerrado" en Cython, mientras que cualquier código escrito para PyPy también puede ejecutarse en CPython.
** Algunas notas adicionales sobre PyPy en producción
Tenga mucho cuidado al hacer cualquier elección que tenga el efecto práctico de "encerrarlo" en PyPy en una gran base de código. Debido a que algunas bibliotecas de terceros (muy populares y útiles) no funcionan bien por las razones mencionadas anteriormente, puede causar decisiones muy difíciles más adelante si se da cuenta de que necesita una de esas bibliotecas. Mi experiencia es principalmente en el uso de PyPy para acelerar algunos (pero no todos) microservicios que son sensibles al rendimiento en un entorno de empresa donde agrega una complejidad insignificante a nuestro entorno de producción (ya tenemos varios idiomas implementados, algunos con diferentes versiones principales como 2.7 vs 3.5 corriendo de todos modos).
He descubierto que usar PyPy y CPython regularmente me obligó a escribir código que solo se basa en garantías hechas por la especificación del lenguaje en sí, y no en detalles de implementación que están sujetos a cambios en cualquier momento. Puede que pensar en estos detalles sea una carga adicional, pero lo encontré valioso en mi desarrollo profesional, y creo que es "saludable" para el ecosistema de Python en su conjunto.
fuente