Esto puede parecer una pregunta extraña para algunos de ustedes.
Soy un programador aficionado de Java. He desarrollado varios juegos, un programa de IA que crea música, otro programa para pintar y cosas similares. Esto es para decirle que tengo experiencia en programación, pero no en desarrollo profesional de aplicaciones comerciales.
Veo muchas conversaciones en este sitio sobre el rendimiento. La gente a menudo debate cuál sería el algoritmo más eficiente en C # para realizar una tarea, o por qué Python es lento y Java es más rápido, etc.
Lo que estoy tratando de entender es: ¿por qué importa esto?
Hay áreas específicas de computación donde veo por qué importa el rendimiento: juegos, donde ocurren decenas de miles de cómputos cada segundo en un ciclo de actualización constante o sistemas de bajo nivel en los que otros programas dependen, como sistemas operativos y máquinas virtuales, etc.
Pero para la aplicación comercial normal, típica de alto nivel, ¿por qué importa el rendimiento?
Puedo entender por qué solía importar, hace décadas. Las computadoras eran mucho más lentas y tenían mucha menos memoria, por lo que había que pensar detenidamente sobre estas cosas.
Pero hoy, tenemos tanta memoria de sobra y las computadoras son tan rápidas: ¿ realmente importa si un algoritmo Java en particular es O (n ^ 2)? ¿Realmente hará una diferencia para los usuarios finales de esta aplicación empresarial típica?
Cuando presiona un botón GUI en una aplicación comercial típica, y detrás de escena invoca un algoritmo O (n ^ 2), en estos días de la informática moderna, ¿realmente siente la ineficiencia?
Mi pregunta se divide en dos:
- En la práctica, ¿importa hoy el rendimiento en un programa comercial normal típico?
- Si es así, deme ejemplos reales de lugares en una aplicación de este tipo, donde el rendimiento y las optimizaciones son importantes.
fuente
Respuestas:
Tienes razón, el rendimiento en las aplicaciones empresariales no es realmente un tema importante, como lo discuten la mayoría de los programadores . Por lo general, las discusiones relacionadas con el rendimiento que escucho de los programadores tienen varios problemas:
En su mayoría son optimizaciones prematuras . Por lo general, alguien quiere "la forma más rápida" de realizar una operación sin razón aparente, y termina haciendo cambios en el código que la mayoría de los compiladores realizan (como reemplazar la división por multiplicación o incluir un método), o pasar días haciendo cambios lo que ayudará a ganar unos pocos microsegundos en tiempo de ejecución.
A menudo son especulativos . Me alegra ver que en Stack Overflow y Programmers.SE, la elaboración de perfiles se menciona con frecuencia cuando la pregunta está relacionada con el rendimiento, pero también me decepciona cuando veo a dos programadores que no saben qué perfil están discutiendo sobre el rendimiento. cambios relacionados que deben hacer en su código. Creen que los cambios harán que todo sea más rápido, pero prácticamente cada vez, no tendrá ningún efecto visible o ralentizará las cosas, mientras que un generador de perfiles los habría señalado a otra parte del código que se puede optimizar fácilmente y que desperdicia el 80% del tiempo.
Se centran solo en aspectos técnicos. El rendimiento de las aplicaciones orientadas al usuario se trata de la sensación: ¿se siente rápido y receptivo, o se siente lento y torpe? En este contexto, los problemas de rendimiento generalmente se resuelven mucho mejor por los diseñadores de experiencia del usuario: una transición animada simple a menudo puede ser la diferencia entre una aplicación que se siente terriblemente lenta y la aplicación que se siente receptiva, mientras que ambas pasan 600 ms. haciendo la operación
Se basan en elementos subjetivos, incluso cuando están relacionados con limitaciones técnicas. Si no se trata de sentirse rápido y receptivo, debe haber un requisito no funcional que especifica qué tan rápido se debe realizar una operación en datos específicos, ejecutándose en un sistema específico . En realidad, sucede más así: el gerente le dice que encuentra algo lento, y luego, los desarrolladores necesitan descubrir qué significa eso. ¿Es lento como en "debería estar por debajo de 30 ms. Mientras que actualmente desperdicia diez segundos", o lento como "quizás podamos reducir la duración de diez a nueve segundos"?
Dicho esto, el rendimiento en general es importante :
En aplicaciones no comerciales, puede volverse crucial. Hay software incorporado , software que se ejecuta en servidores (cuando tiene unos pocos miles de solicitudes por segundo, que no es tan grande, el rendimiento comienza a ser una preocupación), el software se ejecuta en teléfonos inteligentes , videojuegos , software para profesionales (trate de manejar un archivo de 50 GB en Photoshop en una máquina no muy rápida para convencerse) e incluso productos de software ordinarios que se venden a muchas personas (si Microsoft Word dedica el doble de tiempo a realizar todas las operaciones que realiza, el tiempo perdido se multiplica por el número de usuarios se convertirá en un problema).
En las aplicaciones de negocios, hay muchos casos en que los usuarios odian una aplicación que se siente lenta y es lenta. No quiere eso, haciendo que el rendimiento de sus preocupaciones.
fuente
a simple animated transition may often be the difference between an app which feels terribly slow and the app which feels responsive
- ¡aunque estos ciertamente deberían usarse con moderación, para las aplicaciones que ensucian las animaciones y las transiciones en todas partes pueden ser frustrantes si se observan esas transiciones a diario!Sí. Si lo hace. La velocidad de tiempo de ejecución no es la única preocupación que debería tener, y no es tan apremiante como lo fue en 1982, o como todavía lo es en los sistemas integrados de baja potencia, pero siempre es una preocupación, y es importante que comprenda por qué esto es así
Por un lado, la complejidad asintótica que menciona describe el comportamiento de un programa a medida que crece su tamaño de entrada . Un programa no lineal que trata con 10 elementos puede salirse con la suya haciendo un trabajo superfluo, pero te morderá cuando un día tengas que lidiar con 1000, porque no solo parecerá más lento, sino mucho, mucho más lento. Y no sabe (sin un análisis y evaluación comparativa exhaustivos) si ese punto será de 100 elementos, de 1000 elementos o no hasta que llegue a 100.000 elementos. Puede ser difícil de creer, pero elegir el mejor algoritmo de hecho es mucho más fácil que estimar este punto para cada rutina y elegir su implementación dependiendo de esta estimación.
Además, lea sobre los conceptos básicos de la experiencia del usuario. Existen umbrales bien investigados que determinan cómo se percibe la interacción con un programa en función de sus tiempos de respuesta (10 ms, 100 ms, unos segundos, etc.). Al cruzar uno de estos umbrales, los usuarios se desconectarán de su aplicación y, a menos que esté en la posición feliz de escribir un software de monopolio que las personas tienen que usar, los usuarios desconectados se traducen directamente en un valor comercial negativo porque conduce a la pérdida de clientes.
Estas son solo algunas de las razones por las cuales un programador profesional debe conocer la complejidad algorítmica y manejarla de manera responsable. En estos días, generalmente no es necesario salir de su camino y programar un código especialmente optimizado y mal legible para cualquier cosa a menos que resulte ser un bucle interno de tiempo crítico, pero nunca debe invocar una clase de complejidad más alta de lo que obviamente es necesario para hacer el trabajo.
fuente
Si lo hace!
Como solicitó ejemplos, se le ocurren varias situaciones cotidianas:
Manejo de big data : muchas aplicaciones empresariales están respaldadas por bases de datos y, en muchos casos, estas bases de datos se desbordan de datos. Y dado que el espacio en disco es barato, la cantidad de datos grabados y almacenados es una locura. La semana pasada, un cliente se quejó de que su aplicación es muy lenta cuando solo muestra algunos números promedio (consultas de más de un millón de filas ...). También en el uso diario tenemos conversiones de datos por lotes y cálculos con tiempos de ejecución en la liga de varios horas El año pasado, una optimización algorítmica redujo el tiempo de proceso de un lote de 8 a 4 horas, ¡ahora ya no choca con el turno de día!
Capacidad de respuesta : se han realizado estudios de usabilidad (si tengo tiempo, agregaré enlaces a las preguntas relevantes en ux.se ...) de que la satisfacción del usuario está muy relacionada con la capacidad de respuesta. Una diferencia en un tiempo de respuesta de 200 ms frente a 400 ms puede costarle fácilmente un gran porcentaje de sus clientes que lo dejan por sus competidores.
Sistemas integrados : las computadoras no son cada vez más rápidas, son cada vez más lentas y más pequeñas ^ _ ^ El desarrollo móvil tiene un gran impacto en el desarrollo de aplicaciones. Claro que podemos arrojar memoria y ciclos de CPU como Jelly Beans en las computadoras de escritorio modernas, pero ahora su jefe le pide que implemente el algoritmo de análisis del sueño en un extraño reloj o en una tarjeta SIM ...
fuente
No sé qué es un programa de negocios normal típico. Lo que sí sé es que los usuarios siempre terminan alimentando nuestros programas con mucha más información de la que planeamos (a menudo después de preguntarles qué tan grande sería y agregar un margen de seguridad) y que en ese caso, esperan un aumento lineal de en tiempo de ejecución, acepte un comportamiento de inicio de sesión y reclame que la aplicación se congela cuando sucede algo más. Y tienden a considerar el tamaño del resultado más que el tamaño de la entrada, excepto en el caso de que sea obvio por su POV que todos los datos de entrada deben procesarse.
Entonces sí, el rendimiento, al menos en el nivel de complejidad, es importante. La micro-optimización dentro de una clase de complejidad realmente no importa, excepto si es visiblemente peor que la competencia (ya sea en puntos de referencia en algunos mercados o por percepción cruda: cambiar la clase en la progresión "instantánea", "no instantánea pero el usuario no no cambie a otra cosa "," lo suficientemente lento como para que el usuario cambie a otra cosa a riesgo de interrumpir el flujo de acciones "," lo suficientemente lento como para que el usuario inicie la tarea y luego verifique de vez en cuando "," lo suficientemente lento que el usuario planea lanzar la tarea durante el almuerzo, durante la noche, durante el fin de semana ").
fuente
En las aplicaciones empresariales modernas, los problemas de rendimiento no se deben a la falta de CPU o memoria. Pero están en forma de latencias de red, rendimiento de E / S y abstracciones que ocultan todo eso. Todo depende de lo bueno que sea el diseño y la experiencia de los desarrolladores. Incluso una aplicación CRUD simple puede detenerse si se extrae de la base de datos una fila a la vez en lugar de ejecutar una consulta (también conocido como problema N + 1).
El problema es que tener un buen diseño y desarrolladores experimentados es costoso. Y generalmente es mucho más barato irritar a los usuarios que invertir en optimizaciones de rendimiento reales. Hay algunos casos en los que los clientes requieren un alto rendimiento (p. Ej., Navegadores web), pero rara vez se aplican a aplicaciones comerciales comunes.
fuente
Tenga en cuenta que para aplicaciones basadas en servidor, puede tener cientos, miles o incluso millones de usuarios tratando de hacer cosas al mismo tiempo. Un pequeño ahorro en eficiencia en tal situación puede tener un gran impacto en la cantidad de hardware requerida para atender las solicitudes.
fuente
Ciertamente importa mucho.
El problema principal no es ni siquiera ser molesto para el usuario, como experimentar retrasos innecesarios cuando los elementos de la GUI se sobregiran dos o tres veces (¡lo que sí importa en los gráficos integrados!) O simplemente porque el programa tarda mucho en hacer ... lo que sea hace (principalmente cosas poco interesantes). Aunque, por supuesto, eso también es un problema.
Hay tres conceptos erróneos importantes:
Mi esposa trabaja en el extremo superior de un "entorno empresarial típico". La computadora que está usando cuesta aproximadamente 3,5 horas de su tiempo de trabajo. El inicio de Microsoft Outlook lleva, en un buen día, unos 3 minutos hasta que esté listo (6-8 minutos en el trimestre cuando los servidores están bajo una gran carga). Algunas de esas hojas de cálculo de 30,000 filas mencionadas tardan entre 2 y 3 segundos en actualizar un valor durante el cual la computadora está "congelada" (¡sin mencionar cuánto tiempo tarda Excel en iniciarse y abrirse en primer lugar!). Es aún peor cuando se comparte escritorio. Ni siquiera me pongas en marcha con SAP.
Ciertamente importa si cien mil personas pierden cada una 20-25 minutos por día de trabajo sin esperar nada. Esos son millones perdidosque podría, en lugar de perderlos, pagar como dividendos (o pagar salarios más altos).
Claro, la mayoría de los empleados están en el extremo inferior de la escala salarial, pero incluso en el extremo inferior el tiempo es dinero .
fuente
Parece subestimar la rapidez con que crece N ^ 2. Digamos que tenemos una computadora y nuestro algoritmo N ^ 2 tarda 10 segundos cuando N = 10. El tiempo pasa ahora tenemos un nuevo procesador que es 6 veces más rápido que el original, por lo que nuestro cálculo de 10 segundos ahora es menos de dos segundos. ¿Cuánto más grande puede ser N y aún encajar en ese tiempo de ejecución original de 10 segundos? Ahora podemos manejar 24 artículos, un poco más del doble. ¿Cuánto más rápido debería ser nuestro sistema para manejar 10 veces más elementos? Bueno, tendría que ser 100 veces más rápido. Los datos crecen bastante rápido y eliminan el progreso del hardware de la computadora para los algoritmos N ^ 2.
fuente
No creería la cantidad de programas de negocios de terceros que utilizamos en el trabajo, y muchos de ellos son ridículamente lentos de usar en comparación con mis estándares personales. Si los programas fueran algo que uso en casa, los habría reemplazado por uno alternativo hace mucho tiempo.
En algunos casos, la diferencia entra directamente en los costos, ya que algunos programas afectan directamente la cantidad de tareas que puedo realizar durante un día y, por lo tanto, reducen mi productividad y la cantidad de artículos facturables. Por lo tanto, diría que también es muy importante que los programas de negocios tengan al menos un rendimiento suficiente como para no ser el elemento limitante de los ingresos.
Un ejemplo es la gestión de incidentes donde el trabajo se mide en intervalos de 15 minutos (mesa de servicio). Si el programa es lo suficientemente lento como para presionar un ticket para tomar más de 15 minutos (incluido el trabajo real), ralentizará bastante el proceso. Una causa podría ser un acceso lento a la base de datos que simplemente "espera un momento" cada vez que el usuario realiza una acción (completar detalles de resolución, actualizar información de trabajo o similar). Me imagino que hay casos en los que los programas lentos pueden incluso afectar cosas más críticas, como los detalles del paciente del hospital sobre casos de intoxicación urgente, ¿tal vez alergias a medicamentos o algo así?
fuente
Muchas de las otras respuestas cubren el tema a fondo, por lo que les refiero a los motivos y razones. En cambio, quiero dar un ejemplo de la vida real para mostrar cómo una elección algorítmica puede tener implicaciones reales.
http://windowsitpro.com/windows-xp/svchost-and-windows-update-windows-xp-still-problem
El artículo vinculado describe un error en el algoritmo para calcular las actualizaciones de Windows XP. Durante la mayor parte de la vida de Windows XP, el algoritmo de actualización funcionó bien. El algoritmo calcula si un parche ha sido reemplazado por un parche más nuevo y, por lo tanto, no necesita instalarse. Sin embargo, hacia el final, la lista de actualizaciones reemplazadas se hizo muy larga *.
El algoritmo de actualización fue exponencial, donde cada nueva actualización tardó el doble en calcularse que la anterior ( ). Cuando las listas llegaron al rango de 40 actualizaciones (* largo ), tomó hasta 15 minutos, ejecutándose a plena capacidad, para buscar actualizaciones. Esto bloqueó efectivamente muchas máquinas XP durante la actualización. Peor aún, cuando uno iría a instalar las actualizaciones, el algoritmo se ejecutaría
O(n) = 2n
de nuevo , tomando otros 15 minutos. Dado que muchas máquinas tenían configuradas las Actualizaciones automáticas, esto podría bloquear las máquinas durante 15 minutos en cada arranque, y potencialmente nuevamente en una cierta periodicidad.Microsoft usó hacks a corto plazo (eliminando elementos de la lista de actualizaciones) y soluciones a largo plazo para solucionar este problema. Esto era importante porque las últimas versiones de Windows también usaban el mismo algoritmo y algún día podrían enfrentar el mismo problema.
Aquí podemos ver que la elección de un algoritmo tenía implicaciones reales. El algoritmo incorrecto, aunque está bien para la mayor parte de la vida útil del producto, puede tener impactos negativos en el futuro.
fuente
Creo que está interpretando la cantidad de preguntas que se hacen sobre el rendimiento como una indicación de que los requisitos de rendimiento para las aplicaciones comerciales son importantes en lugar de reconocer que mejorar el rendimiento es difícil . Solo lograr que funcione puede lograrse mediante técnicas de fuerza bruta, prueba y error o copiando y pegando código de ejemplo.
Cualquiera puede tener suerte y seguir haciendo cambios hasta que algo funcione más rápido, pero eso rara vez funciona. Debido a la falta de experiencia, los desarrolladores verán ayuda externa. En algunos entornos, las mejoras de rendimiento son problemas únicos, por lo que hacer una pregunta específica en un sitio como StackOverflow puede ser la única opción. Además, muchos consultores ganan dinero al poder intervenir y solucionar este tipo de problemas.
fuente
Depende en gran medida de cómo defina "buen rendimiento". Sus algoritmos siempre deben usar la mejor complejidad posible. Abusa de las lagunas para acelerar tu jaula promedio. Buffer y preload / precompile siempre que sea posible en un programa interactivo.
Hay otra definición de "buen rendimiento": optimizar las constantes de su clase de complejidad. Aquí es donde C ++ obtiene su título, donde la gente comienza a llamar a Java lento, donde un 5% menos de tiempo de ejecución parece ser el santo grial. Usando esta definición tienes razón. El hardware de la computadora se vuelve más complicado con el tiempo, mientras que los compiladores mejoran cada vez más. En algún momento, realmente no puede optimizar el código de gama baja mejor que el compilador, así que déjelo y concéntrese en sus algoritmos.
En ese momento, usar Java / Haskell / C ++ se convierte en otra decisión de diseño. La reducción de números se puede hacer a través de OpenCL en su GPU. Las interfaces de usuario necesitan algoritmos de tiempo constante y son buenas. La salida y la modularidad son más importantes que alinear sus clases para una utilización de caché un 20% mejor. Multithreading se vuelve importante, porque las personas no quieren una aplicación rápida, quieren una que responda. Lo que no es importante es que su aplicación sea constantemente un 10% más lenta de lo que podría ser. Incluso el 50% está bien (pero la gente comienza a hacer preguntas entonces). Concéntrese en lo correcto, la capacidad de respuesta y la modularidad.
Me encanta programar en Haskell o al menos en una forma funcional (incluso en C ++). Poder escribir pruebas fácilmente para todo su programa es mucho más importante que ser un poco más rápido en trabajos por lotes.
fuente
Muy simple: costo
Mi empleador anterior tenía un sistema de gestión de aprendizaje alojado en servidores físicos como modelo SaaS. El montón de JVM se configuró en 2 GB para las máquinas más antiguas y 3 GB para las máquinas más nuevas y ejecutamos varias instancias por máquina. Uno pensaría que eso sería suficiente.
Antes de comenzar, había un equipo de rendimiento responsable de hacer que el sistema respondiera y escalara. Descubrieron que había ciertos datos que consultamos constantemente desde la base de datos. Incluso había una tabla en la que nos unimos a la mayoría de las consultas para recuperar una columna. Esos datos rara vez cambian.
El problema es que teníamos 2 GB para trabajar. Entonces, la solución obvia es comenzar a almacenar en caché todos los datos leídos con frecuencia. Luego tuvimos problemas de memoria, comenzando justo antes de que me uniera.
Había 2 escuelas de pensamiento en esto:
El segundo argumento ganó y pasé más de un año ajustando nuestro uso de memoria.
Mi empleador actual también alberga un sistema de gestión de aprendizaje, pero lo hace de manera un poco diferente. La escalabilidad es tan pobre que una sola instalación (dividida en 4 servidores virtuales con equilibrio de carga) solo puede manejar 80 clientes. Algunos de nuestros clientes más grandes incluso obtienen su propio conjunto de servidores. La mayoría de los problemas que conducen a esto son problemas de rendimiento, como consultas SQL que acaparan todos los ciclos de la CPU, pérdidas de memoria, código redundante que hace lo mismo varias veces. Incluso tenemos una aplicación interna creada cuyo único propósito es reiniciar los servidores cuando no funcionan mal. Hay un empleado que mantiene esa herramienta (junto con otras responsabilidades).
Se suscribieron a la primera escuela de pensamiento que mencioné anteriormente: lanzar más hardware porque los costos de hardware son más baratos que los salarios de los desarrolladores.
Esto no funcionó tan económicamente como se esperaba. Entre el hardware, las licencias de software y el personal de soporte para manejar los servidores, gastamos millones cada año para evitar que un desarrollador dedique tiempo a crear códigos.
Cuando me uní, me hicieron responsable de solucionar nuestros problemas de disponibilidad. Dado que la mayoría de nuestros problemas de disponibilidad se debieron al bajo rendimiento, he estado ajustando nuestro código de rendimiento y la escalabilidad ha mejorado sustancialmente, con un tiempo de actividad mucho mejor. Estamos listos para comenzar a aumentar la densidad. No hace falta decir que mi salario no está cerca de un millón (¡ojalá!), Así que gastar dinero en hacer que ajuste el rendimiento del código va a terminar ahorrándonos millones por año.
TL; DR
Si realiza un análisis exhaustivo de costo / beneficio, verá que es más barato simplemente arreglar el código. Un problema de rendimiento conocido que ignora se convierte en deuda técnica .
fuente
Entendí su pregunta de esta manera: para lograr desempeños lo suficientemente buenos (es decir, los usuarios están contentos y mi backend no se avergüenza), ¿necesito entender la teoría sobre la complejidad algorítmica?
Depende de lo que entiendas por aplicación comercial "típica". En muchos casos, especialmente en sistemas de información CRUD similares, la respuesta sería no. Para estos, "simplemente" (a veces es realmente difícil) necesitará poder rastrear los cuellos de botella del rendimiento: ¿me perdí un índice en mi base de datos? ¿Envío demasiados datos a través de la red? ¿Tengo un reloj de mil dólares en mi front-end angular.js? Se trata de construir una arquitectura de sonido, conocer bien su pila de tecnología y evitar la falta de sentido. Puede lograrlo si es un buen artesano, no necesariamente un informático. Otra forma de decirlo es que los chicos que crearon el optimizador de consultas de Oracle se ocuparon de la complejidad algorítmica, solo necesitas usar adecuadamente lo que te proporcionaron.
Ahora hay excepciones. Si hablamos de big data o aprendizaje automático, debe saber lo que está haciendo y no solo usar los algoritmos predeterminados disponibles. Incluso en el frente, si comienza a construir visualizaciones de datos avanzadas, algunas de ellas pueden implicar un costo de complejidad no lineal (por ejemplo, gráficos de diseño forzado).
Hoy en día, estas excepciones se están volviendo cada vez más comunes y el mercado está bastante seco cuando busca personas que puedan manejarlos. Entonces: sí, puede tener éxito sin experiencia en informática, pero lo será aún más con algunos.
fuente
Los otros respondedores han cubierto la mayoría de los puntos básicos, pero para tareas que pueden ser paralelas, el software ineficiente conduce a mayores costos de hardware en forma de más servidores, que usan más energía y requieren más espacio y mantenimiento.
fuente