Hace poco hice una pregunta sobre Stack Overflow para descubrir por qué isset () era más rápido que strlen () en PHP . Esto planteó preguntas sobre la importancia del código legible y si valía la pena considerar las mejoras de rendimiento de microsegundos en el código.
Mi padre es un programador retirado y le mostré las respuestas. Estaba absolutamente seguro de que si un codificador no considera el rendimiento en su código, incluso a nivel micro, no son buenos programadores.
No estoy tan seguro: ¿quizás el aumento en la potencia de cómputo significa que ya no tenemos que considerar este tipo de mejoras de micro rendimiento? ¿Quizás este tipo de consideración depende de las personas que escriben el código de idioma real? (de PHP en el caso anterior).
Los factores ambientales podrían ser importantes: Internet consume el 10% de la energía mundial. Me pregunto cuán derrochador son unos pocos microsegundos de código cuando se replican billones de veces en millones de sitios web.
Me gustaría saber las respuestas preferiblemente basadas en hechos sobre programación.
¿Es importante la microoptimización al codificar?
Mi resumen personal de 25 respuestas, gracias a todos.
A veces necesitamos preocuparnos realmente por las micro optimizaciones, pero solo en circunstancias muy raras. La fiabilidad y la legibilidad son mucho más importantes en la mayoría de los casos. Sin embargo, considerar la micro-optimización de vez en cuando no hace daño. Una comprensión básica puede ayudarnos a no tomar malas decisiones obvias al codificar como
if (expensiveFunction() || counter < X)
Debiera ser
if (counter < X || expensiveFunction())
( Ejemplo de @ zidarsk8 ) Esta podría ser una función económica y, por lo tanto, cambiar el código sería una microoptimización. Pero, con una comprensión básica, no tendría que hacerlo, porque lo escribiría correctamente en primer lugar.
coder does not consider performance in their code even at the micro level, they are not good programmers
Es muy diferente de la micro-optimización. Es solo una buena codificación.Respuestas:
Estoy de acuerdo y en desacuerdo con tu padre. Se debe pensar en el rendimiento temprano, pero solo se debe pensar en la micro-optimización temprano si realmente sabe que se pasará un alto porcentaje de tiempo en pequeñas secciones de código vinculadas a la CPU.
El problema con la microoptimización es que generalmente se realiza sin tener ningún concepto de cómo los programas realmente pasan más tiempo del necesario.
Este conocimiento proviene de la experiencia en el ajuste del rendimiento, como en este ejemplo , en el que un programa aparentemente sencillo, sin ineficiencias evidentes, se lleva a cabo a través de una serie de pasos de diagnóstico y aceleración, hasta que es 43 veces más rápido que al principio.
Lo que muestra es que realmente no puedes adivinar o intuir dónde estarán los problemas. Si realiza un diagnóstico, que en mi caso es una pausa aleatoria , las líneas de código responsables de una fracción significativa de tiempo se exponen preferentemente. Si observa esos, puede encontrar código sustituto y, por lo tanto, reducir el tiempo total en aproximadamente esa fracción.
Otras cosas que no arregló aún toman tanto tiempo como lo hicieron antes, pero dado que el tiempo general se ha reducido, esas cosas ahora toman una fracción mayor, por lo que si lo vuelve a hacer, esa fracción también se puede eliminar. Si sigue haciendo esto en varias iteraciones, así es como puede obtener aceleraciones masivas , sin necesariamente haber realizado ninguna microoptimización .
Después de ese tipo de experiencia, cuando aborda nuevos problemas de programación, llega a reconocer los enfoques de diseño que inicialmente conducen a tales ineficiencias. En mi experiencia, proviene del diseño excesivo de la estructura de datos, la estructura de datos no normalizada, la dependencia masiva de las notificaciones, ese tipo de cosas.
fuente
La microoptimización solo es importante si los números lo dicen.
Los requisitos con los que está desarrollando deben tener alguna especificación de los datos de rendimiento, si el rendimiento es un problema para el cliente o usuario. A medida que desarrolla software, debe probar el rendimiento de su sistema contra estos requisitos. Si no cumple con los requisitos de rendimiento, debe perfilar su base de código y optimizar según sea necesario para alcanzar los requisitos de rendimiento. Una vez que esté dentro del rendimiento mínimo requerido, no es necesario exprimir más el rendimiento del sistema, especialmente si va a comprometer la legibilidad y la facilidad de mantenimiento del código (en mi experiencia, el código altamente optimizado es menos legible y mantenible, pero no siempre). Si puede obtener ganancias de rendimiento adicionales sin degradar los otros atributos de calidad del sistema,
Sin embargo, hay casos en los que el rendimiento es de suma importancia. Estoy pensando principalmente en sistemas en tiempo real y sistemas integrados. En los sistemas en tiempo real, cambiar el orden de las operaciones puede tener un efecto enorme en el cumplimiento de los plazos estrictos que se requieren para una operación adecuada, tal vez incluso influya en los resultados de los cálculos. En los sistemas integrados, normalmente tiene memoria limitada, potencia de CPU y potencia (como en la batería), por lo que debe reducir el tamaño de sus archivos binarios y la cantidad de cálculos para maximizar la vida útil del sistema.
fuente
Cada vez que alguien pregunta acerca de la optimización , recuerdo la cita de Michael A. Jackson
Cita de Wikipedia corregida para inglés británico. * 8 ')
Implícito en la segunda regla es perfilar su código y solo pasar tiempo optimizando cosas que marcarán la diferencia.
Al programar en asamblea, la afirmación de su padre era correcta. Pero eso está mucho más cerca del metal de lo que la mayoría de la gente programa en estos días. Hoy, incluso intentar optimizarse (sin perfilar) puede hacer que su código se ejecute más lentamente que si hubiera hecho algo de la manera más común, ya que es más probable que los compiladores JIT modernos optimicen la forma común .
Incluso en C tienes que ser bastante bueno en la optimización para saber más sobre cómo optimizar una sección de código que el compilador.
Si no está familiarizado con gran parte de lo que Ulrich Drepper habla en su excelente artículo Lo que todo programador debe saber sobre la memoria , entonces es probable que sea un perdedor incluso tratando de optimizarlo. Sin embargo, al contrario del título de los documentos (que en realidad es un homenaje a lo igualmente fantástico de David Goldberg Lo que todo informático debe saber sobre la aritmética de punto flotante ) no tener este nivel de comprensión no necesariamente te impide ser un buen programador, solo un tipo diferente de programador.
isset()
vs.strlen()
en PHPNo conozco PHP, por lo que realmente no es obvio lo
isset()
que debe hacer. Puedo inferirlo del contexto, pero esto significa que será igualmente oscuro para los programadores PHP novatos e incluso podría causar que los programadores más experimentados tomen el doble. Este es el tipo de uso idiomático de un lenguaje que puede hacer que el mantenimiento sea una pesadilla.No solo eso, sino que no hay garantía de que
isset()
siempre sea más eficiente, solo porque ahora es más eficiente. Una optimización ahora podría no ser una optimización el próximo año, o en 10 años. Las CPU, los sistemas, los compiladores mejoran y cambian con el tiempo. Si el rendimiento de PHPstrlen()
es un problema, PHP podría modificarse en el futuro, entonces todas las optimizaciones de isset () pueden necesitar eliminarse para optimizar el código una vez más.Cada optimización tiene el potencial de convertirse en una futura anti-optimización , por lo que debe considerarse un posible olor a código, que debe mantenerse al mínimo.
Un ejemplo de experiencia personal.
Como ejemplo de tal anti-optimización , una vez tuve que desinfectar una enorme base de código llena con el código del formulario
if x==0 z=0 else z=x*y
porque alguien había asumido que una multiplicación de coma flotante siempre iba a ser más costosa que una rama. En la arquitectura de destino original, esta optimización hizo que el código se ejecutara un orden de magnitud más rápido, pero los tiempos cambian.Cuando intentamos usar este código en una CPU más moderna que estaba altamente canalizada, el rendimiento fue terriblemente malo: cada una de estas declaraciones causa un vaciado de tubería. Simplificando todas estas líneas de código para
z=x*y
hacer que el programa ejecute un orden de magnitud más rápido en la nueva arquitectura, restaurando el rendimiento perdido por la anti-optimización .Los problemas que normalmente tenemos que optimizar para hoy son muy diferentes a los que tuvimos que optimizar hace 20 o incluso 10 años.
Luego nos preocupamos por hacer la mayor cantidad de trabajo por ciclo de reloj, ahora es más probable que nos preocupemos por los enjuagues de tuberías, las predicciones erróneas de ramas y las fallas de caché a nivel de CPU, pero las cerraduras y la comunicación entre procesos se están volviendo mucho más significativas a medida que avanzamos hacia múltiples arquitecturas de proceso y multiprocesador. El artículo de Drepper realmente puede ayudar a comprender muchos de estos problemas.
fuente
Como regla general: el 95% de su código se ejecuta el 5% del tiempo. No tiene sentido optimizar antes de perfilar / comparar su código y ver cuáles son los 5% que se ejecutan el 95% del tiempo.
Cada idiota puede hacer micro-optimización y cualquier compilador / tiempo de ejecución decente lo hará por usted.
Optimizar un buen código es trivial. Escribir código optimizado e intentar que sea bueno después de eso es tedioso en el mejor de los casos e insostenible en el peor.
Si en serio se preocupa por su rendimiento, entonces no usar PHP para el rendimiento del código crítico. Encuentre los cuellos de botella y vuelva a escribirlos con extensiones C. Incluso la micro optimización de su código PHP más allá del punto de ofuscación no le dará tanta velocidad.
Personalmente, me gustaba mucho la microoptimización cuando comencé a programar. Porque es obvio. Porque te recompensa rápidamente. Porque no tienes que tomar decisiones importantes. Es el medio perfecto de procrastinación. Le permite escapar de las partes realmente importantes del desarrollo de software: el diseño de sistemas escalables, flexibles, extensibles y robustos.
fuente
Estoy de acuerdo con su padre: "Si un codificador no considera el rendimiento en su código incluso a nivel micro, no son buenos programadores". La clave es "considerar el rendimiento". Eso no es equivalente a "hacer micro optimizaciones en cada paso".
Estoy de acuerdo con la mayoría de los otros comentarios: lo que solía hacer que los programas de C sean más rápidos puede que no lo haga hoy, pero hay otras cosas serias que considerar: ¿Debo usar C o C ++? Las clases con operadores simples sobrecargados pueden matar el rendimiento si los usa mucho. ¿Eso importa? Depende de su aplicación, pero si ni siquiera lo CONSIDERA, no es un muy buen programador. Algunas personas podrían considerarlo durante unos 2 milisegundos y descartarlo, pero creo que demasiados literalmente ni siquiera lo consideran.
La realidad es que con la optimización, el código puede ser más difícil de leer. El código tardará más en escribir. El código estará en algún lugar entre un poco más rápido y un orden de magnitud más rápido (eso es raro). Sus clientes probablemente no notarán la diferencia.
Otra realidad es que a la gente le gusta reutilizar el código, y donde termina puede ser muy diferente de cuando lo escribió. De repente, a las personas les puede importar.
Como ejemplo, supongamos que escribió algo como Angry Birds en una PC o para una consola de juegos. No tuvo en cuenta la optimización en su sistema de física y su sistema de gráficos, porque los núcleos duales de 2.5 GHz son básicamente el mínimo en estos días, y su juego funciona lo suficientemente bien. Luego aparecen los teléfonos inteligentes y quieres portarlos. Oh maldita sea, ¿un núcleo ARM de 600 MHz ?
Piense en un sitio web: algo lanzado en un fin de semana como Hot or Not . Utiliza cualquier base de datos que sea útil, escribe todo con un rápido desarrollo en mente, inicia el envío enviando una URL a tus amigos. Tres meses después, su servidor se está muriendo por sobrecarga y no hay nada que pueda hacer para escalar. Pasa todo el tiempo. Los sitios web más grandes tienen facturas de energía medidas en cientos de kilovatios o incluso megavatios. Piense en eso, hay megavatios que se guardarán a través de la optimización del código.
Como dijo tu padre, al menos debes considerarlo . La mayoría de la gente ni siquiera sabe cuánto rendimiento hay en la mesa y pasa desapercibido con un comentario rápido sobre "optimización prematura" y "no lo hagas". Estos no son buenos programadores.
Esta no es una opinión popular en estos sitios. Adiós puntos de reputación ...
fuente
Primero tomemos su caso: PHP
En general,
No pasaría mucho tiempo "TOOOOO" optimizando mi código en un lenguaje dinámico como Python o Ruby , porque NO están diseñados para tareas de cálculo intensivo de números de CPU. Resuelven diferentes clases de problemas donde modelar una situación del mundo real de una manera elaborada (que es fácil de leer y mantener), lo que se llama expresividad , es más importante que la velocidad. Si la velocidad fuera la principal preocupación, no serían dinámicos en primer lugar.
Para los programas compilados (C ++, Java), la optimización es más crucial. Pero allí también, primero tienes que mirar la naturaleza / dominio / propósito del programa que estás escribiendo. También debe sopesar cuidadosamente el tiempo para micro-optimizar contra las ganancias de esa optimización. Si necesita aún más optimización, entonces también puede considerar ir un paso hacia abajo y codificar esas partes de su código en ensamblador.
Entonces, para responder a su pregunta original: "¿Es importante la microoptimización al codificar?" -- La respuesta es, depende --
La microoptimización (optimización del código para el caso) no solo lleva mucho tiempo, sino que "distorsiona" la legibilidad natural de su código, lo que lo hace pesado en mantenimiento. Siempre considérelo como un último recurso: siempre trate de optimizar toda la aplicación adoptando un mejor hardware y una mejor arquitectura que la optimización de archivos de código individuales.
fuente
Parece que hay muchas respuestas que dicen que la micro optimización es
Pero bueno, sé que hay algunas optimizaciones en las que no hay impacto de legibilidad, y me gusta hacerlas por diversión. Vi en algunas de mis tareas escolares (todas basadas en la velocidad), que siempre es bueno considerar la micro optimización al escribir declaraciones condicionales como:
siempre es mejor que
Hay bastantes maneras de "acelerar" su código de esa manera y la diferencia suele ser insignificante (aunque no siempre), pero me siento mejor si lo escribo así.
No sé si alguien incluso considera esto como una optimización real, pero creo que un programador debería saber y considerar estas cosas al escribir su código.
fuente
cheap() && expensive()
es una optimización deexpensive () && cheap()
invita a las personas a sustituir ciegamente una por la otra sin tener en cuenta el cambio semántico significativo que crea (en los idiomas donde&&
está el operador de cortocircuito).if (x<100 && isPrime(x))
, solo para aclararlo.Al principio de mi carrera, declaraciones generales como "no micro-optimizar" me causaron mucha confusión. Todo es circunstancial; así, la razón por la cual la gente dice "mejor práctica" en lugar de "hacer esto".
La "mejor práctica" es la mejor opción teniendo en cuenta todas las circunstancias. Por ejemplo, LINQ y Entity Framework deben usarse en lugar de SQL en línea. En mi empresa estamos en SQL Server 2000 . SQL Server 2000 no es compatible con Entity Framework. Las mejores prácticas requieren:
Sé por experiencia que esto no va a suceder. Entonces, podría dejar de fumar, estresarme sin fin o no seguir la mejor práctica.
Hay consideraciones políticas, técnicas y monetarias detrás de las decisiones que afectan el resultado general. Recuerda este hecho al tomar una decisión y elige tus batallas sabiamente.
" Para todo hay una temporada, un tiempo para cada actividad bajo el cielo " .
fuente
LINQ and Entity Framework should be used in lieu of inline SQL
- Hasta que realmente necesite SQL en línea para optimizar algo; el SQL que produce EF no siempre es óptimo.Esto siempre es una compensación.
Primero, la industria informática se trata de dinero al final. Lo que debe hacer como desarrollador es generar valor para el cliente para que obtenga dinero (eso es una simplificación excesiva, pero el punto principal está aquí).
El tiempo del desarrollador cuesta dinero. La potencia de la máquina también cuesta dinero. Por lo general, este segundo costo es mucho más bajo que el primero. Por lo tanto, este es un capital para tener un código legible y un código que se pueda mantener, para que el desarrollador pueda pasar la mayor parte de su tiempo entregando valor.
La micro optimización puede, en algunos casos, ser importante. Pero generalmente implican un código menos legible o un código menos extensible (este no es el caso de su ejemplo vinculado, pero en general lo es). Esto costará en algún momento el tiempo del desarrollador. Esta vez es más costoso que la potencia de la máquina, esto es un desperdicio.
En segundo lugar, la microoptimización en un proyecto grande puede dificultar cada vez más el mantenimiento / evolución. El problema con eso es que, al evolucionar, ahora puede ser imposible realizar alguna otra optimización. Con una aplicación en evolución, generalmente terminará con una solución que es más lenta de lo que hubiera tenido sin hacer esas optimizaciones.
En tercer lugar, la optimización es a menudo irrelevante ya que la complejidad del algoritmo generalmente superará cualquier microoptimización que podría haber hecho si el conjunto de datos crece. Lamentablemente, como la micro-optimización hace que su código sea más difícil de mantener / evolucionar, esa optimización puede ser más difícil de hacer.
En algún momento, el valor está en esta optimización (piense en los programas críticos de latencia, como en los videojuegos o el piloto automático de un avión). Pero esto tiene que ser demostrado. Por lo general, su programa pasa la mayor parte del tiempo en una porción limitada de código. Independientemente de la microoptimización que haga, nunca obtendrá sus programas de manera mucho más rápida sin identificar el cuello de botella y trabajar en esta parte.
Hacer su pregunta como lo hizo demostró que no evaluó el problema en un programa real. En este caso, podrías haber hecho el truco y notar si era más rápido o no. Entonces preguntabas eso antes de tener algún problema. Aquí es donde está el problema. Estaba manejando el problema de la optimización de la manera incorrecta.
Dado que el mantenimiento y la evolución suelen ser más valiosos que la microoptimización, asegúrese de tener la interfaz correcta antes de realizar ninguna. Luego, si partes de su programa son lo suficientemente abstractas entre sí, puede micro-optimizar una sin estropear todo. Esto requiere que su interfaz se ejecute durante el tiempo suficiente para ser confiable.
fuente
El rendimiento es una característica
El artículo de Jeff Atwood es excelente para construir un sitio web de alto rendimiento y la importancia de hacerlo ...
Dicho esto, no se concentre en la microoptimización hasta que lo necesite. Hay una optimización más rentable que puede realizar. Concéntrese en la arquitectura, no en el código. La mayoría de los sitios web que he visto que han funcionado lentamente tuvieron problemas de alto nivel (capa de servicio web innecesaria, diseño de base de datos deficiente, arquitecturas demasiado complicadas) que no solo afectaron negativamente el rendimiento sino que fueron profundamente arraigados y difíciles de solucionar.
Cuando crea un sitio web, es mucho más probable que el código del lado del cliente y la lógica de la base de datos causen problemas de rendimiento que el código del lado del servidor. Sin embargo, si tiene problemas de rendimiento, lo sabrá, perfile aún mejor su código y podrá encontrarlos desde el principio.
fuente
El tiempo de desarrollador cuesta más que el tiempo de computadora. Eso suele ser lo que desea optimizar. Pero:
select (select count(*) from foo) >= 1
no es lo mismo queselect exists(select 1 from foo)
.fuente
¿Qué quieres optimizar?
"Optimizar" no siempre significa hacer que el código se ejecute lo más rápido posible. Hay momentos en los que es importante encontrar la forma más rápida de hacer algo, pero eso no es tan común en la mayoría de los códigos. Si los usuarios no pueden notar la diferencia entre 50 y 100 microsegundos, efectivamente no hay diferencia entre los dos en el código que solo se ejecutará ocasionalmente. Aquí hay un ejemplo:
Si necesita actualizar continuamente una visualización de la longitud de la entrada del usuario y la cantidad de tiempo que toma cualquiera de las dos rutinas para determinar que la longitud es mucho menor que el tiempo entre dos pulsaciones de tecla consecutivas, realmente no importa qué rutina tu usas. Por otro lado, si necesita determinar la longitud de mil millones de cadenas, probablemente deba prestar mucha atención a las diferencias de rendimiento entre las diferentes rutinas. En el primer caso, es posible que prefiera escribir código que sea fácil de entender y verificar; En el segundo caso, puede estar dispuesto a cambiar la legibilidad por la velocidad.
En cualquier caso, si va a optimizar su código, debe perfilarlo antes y después de cualquier cambio que realice. Los programas en estos días son tan complicados que a menudo es difícil saber dónde están los cuellos de botella; la creación de perfiles lo ayuda a optimizar el código correcto y luego muestra que las optimizaciones que realizó realmente funcionaron.
No dijiste cuándo se retiró tu padre o qué tipo de programación hizo, pero su reacción no es sorprendente. Históricamente, la memoria, el almacenamiento secundario y el tiempo de computación eran caros y, a veces, muy caros. En estos días, todas esas cosas se han vuelto muy baratas en comparación con el tiempo del programador. Al mismo tiempo, los procesadores y compiladores han podido optimizar el código de una manera que los programadores nunca podrían igualar. Los días en que los programadores usan pequeños trucos para quemar algunas instrucciones de máquina aquí y allá se han ido.
fuente
No es importante realizar una micro optimización mientras se escribe el código. La optimización debe hacerse con la ayuda de un generador de perfiles, optimizando el código donde importa.
SIN EMBARGO , un programador debe tratar de evitar hacer cosas obviamente estúpidas mientras escribe el código.
Por ejemplo, no realice operaciones costosas repetidas dentro de un bucle. Almacene el valor en una variable fuera del ciclo y úselo. No haga cosas como comparaciones de cadenas o expresiones regulares una y otra vez en una función a menudo llamada, cuando puede subir un nivel, haga la comparación y conviértala en un entero o una referencia de función o una clase derivada.
Estas cosas son fáciles de recordar para un programador experimentado y casi siempre mejoran la calidad del código.
fuente
Al decidir qué optimizar, recuerde siempre la ley de Amdahl . Vea el enlace para matemática precisa; La declaración concisa para recordar es:
Esta es la razón por la cual la gente siempre dice que no vale la pena optimizar partes de su programa que no ocupan más que un pequeño porcentaje del tiempo de ejecución total. Pero ese es solo un caso especial de un principio más general. La ley de Amdahl le dice que si necesita hacer que todo el programa se ejecute el doble de rápido, debe acelerar cada pieza en un promedio del 50%. Le dice que si necesita procesar veinte gigabytes de datos, solo hay dos formas de hacerlo más rápido que el tiempo que lleva leer veinte gigabytes del disco: obtener un disco más rápido o reducir los datos.
Entonces, ¿qué dice la ley de Amdahl sobre las micro optimizaciones? Dice que tal vez valen la pena si se aplican en todos los ámbitos. Si puede reducir el uno por ciento del tiempo de ejecución de cada función en su programa, ¡felicidades! Has acelerado el programa en un uno por ciento. ¿Valió la pena hacerlo? Bueno, como compilador, estaría encantado de encontrar una optimización que hiciera eso, pero si lo haces a mano, diría que buscas algo más grande.
fuente
Depende de la etapa de desarrollo en la que se encuentre, cuando inicialmente comienza a escribir algo, las micro optimizaciones no deberían considerarse, ya que obtendrá más ganancias de rendimiento al usar buenos algoritmos que al usar micro optimizaciones. Además, considere lo que está desarrollando, ya que las aplicaciones sensibles al tiempo verán más beneficios de las consideraciones de micro optimización que las aplicaciones comerciales genéricas.
Si está probando y extendiendo software, entonces las micro optimizaciones probablemente lo perjudiquen, tienden a hacer que el código sea más difícil de leer e incluso introducen su propio conjunto único de errores que deben corregirse junto con cualquier otra cosa que deba corregirse.
Si realmente está recibiendo quejas de los usuarios sobre el código lento, entonces valdría la pena considerarlas, pero solo si todo lo demás se ha resuelto, a saber:
Si todas esas preguntas han sido respondidas y todavía tiene problemas de rendimiento, entonces podría ser el momento de comenzar a usar micro optimizaciones en el código, pero es probable que otros cambios (es decir, un mejor código, un mejor algoritmo, etc.) le va a generar más de una ganancia de rendimiento que una microoptimización.
fuente
La velocidad de ejecución es uno de los muchos factores que contribuyen a la calidad de un programa. Muchas veces, la velocidad tiene una correlación inversa con la legibilidad / mantenibilidad. En casi todos los casos, el código debe ser legible para que se pueda mantener el código. El único momento en que la legibilidad puede verse comprometida es cuando la velocidad es un requisito esencial. El requisito de hacer que el código sea más rápido de lo que permite la legibilidad / mantenibilidad total casi nunca es aplicable, pero hay ciertos casos en los que lo hará. Lo principal a recordar es que el código micro optimizado a menudo es código hacky, por lo que, a menos que haya un requisito definido en alguna parte, casi siempre es la forma incorrecta de resolver el problema. Por ejemplo, el usuario casi nunca notará la diferencia entre tiempos de ejecución de .5 segundos y 1 segundo en operaciones CRUD, así que no necesitas entrar en un ensamblaje-interop-hackfest para llegar a esos .5 segundos. Sí, podría volar un helicóptero para trabajar y sería 10 veces más rápido, pero no lo hago debido al precio y al hecho de que el helicóptero es mucho más difícil de volar.Cuando micro optimiza el código innecesariamente, esto es exactamente lo que está haciendo: agregar complejidad y costo innecesarios para alcanzar un objetivo superfluo.
fuente
La microoptimización es importante cuando golpeas una restricción. Lo que le interesa puede ser la memoria, el rendimiento, la latencia o el consumo de energía. Tenga en cuenta que estas son características de nivel de sistema; no necesita (y no puede) optimizar cada función de todas las formas.
Es más probable que los sistemas integrados necesiten micro-optimización porque las restricciones se ven afectadas más fácilmente. Sin embargo, incluso allí la microoptimización solo te lleva hasta cierto punto; no puede micro-optimizar su salida de un mal diseño. El punto sobre el buen diseño en un sistema es que puede razonar sobre el sistema en su conjunto. Los componentes que necesitan micro-optimización deben estar claramente expuestos y optimizados de manera que no comprometan el diseño del sistema.
Tenga en cuenta que los pequeños sistemas "integrados" de hoy en día pueden estar bastante cerca de los Vaxen o PDP-11 de antaño, por lo que estos problemas solían ser más comunes. En un sistema moderno de propósito general que hace computación comercial general moderna, la microoptimización es rara. Probablemente esto sea parte de por qué tu padre toma la posición que él toma.
Sin embargo, no importa si se trata de nanosegundos, milisegundos, segundos u horas; Los problemas son los mismos. Deben evaluarse en el contexto del sistema y lo que está tratando de lograr.
Este es un ejemplo de una pregunta reciente que respondí en Stack Overflow para un caso en el que era necesaria una micro optimización: codificadores de video de código abierto para un sistema embebido .
fuente
El mayor problema con la microoptimización es que te lleva a escribir un código más difícil de mantener.
Otro problema depende de la configuración de la computadora, a veces su microoptimización podría tener un peor rendimiento que sin la 'optimización'.
Hacer muchas micro-optimizaciones consumirá mucho tiempo luchando contra algo que realmente no importa.
Un mejor enfoque es hacer un código más limpio, más fácil de mantener, y si tiene problemas de rendimiento, ejecuta un perfil para descubrir qué es lo que realmente hace que su código sea lento. Y sabiendo exactamente lo que es realmente malo, puede solucionarlo.
No estoy diciendo que no hacer micro optimizaciones es una excusa para escribir código estúpido.
fuente
Si comienza a preocuparse por los milisegundos, debería considerar abandonar PHP y usar C o Assembly en su lugar. No es que quisiera hacer esto, simplemente no tiene sentido discutir tales números y usar un lenguaje de secuencias de comandos. ¿Su código itera con este comando que a menudo de todos modos?
Los factores ambientales están fuera de discusión aquí, esos servidores funcionan 24/7 de todos modos y si realmente procesan algo, solo importaría si realmente es una tarea que se ejecuta durante mucho tiempo.
Lo más probable es que la luz en su oficina y la energía que nuestras computadoras usaban mientras todos escribíamos preguntas y respuestas, consumían mucha más energía que cualquier tipo de micro optimización que pueda aplicar razonablemente a sus aplicaciones.
fuente
Debe elegir el mejor algoritmo simple para la tarea. La razón por la que debe ser simple es mantener el código legible. La razón por la que debe ser la mejor es evitar comenzar con malas características de tiempo de ejecución. No elija ciegamente BubbleSort cuando sepa que tendrá grandes conjuntos de datos. Sin embargo, está bien para el tipo ocasional de 10 elementos.
ENTONCES, si los números de perfil muestran que su elección del mejor algoritmo simple no fue lo suficientemente bueno, puede comenzar la optimización (que generalmente es el costo de la legibilidad).
fuente
start out with bad runtime characteristic
no comience deliberadamente con una característica de mal tiempo de ejecución.Lo dije antes, y lo diré aquí: "La optimización prematura es la raíz de todo mal" . Esta debería ser una de las reglas en el centro de la mente de cualquier programador.
El código puede, hasta cierto punto, siempre ser más rápido de lo que es actualmente. A menos que esté empaquetando a mano el ensamblaje con un chip en particular en mente, siempre hay algo que ganar con la optimización. Sin embargo, a menos que QUIERAS empacar a mano todo lo que haces, tiene que haber un objetivo cuantitativo, que una vez que lo cumples, dices "eso es suficiente" y dejas de optimizar, incluso si todavía hay una mirada deslumbrante por el rendimiento. usted en la cara
El código hermoso, elegante y extremadamente eficaz es inútil si no funciona (y por "trabajo" me refiero a producir la salida esperada dadas todas las entradas esperadas). Por lo tanto, producir código que funcione SIEMPRE debe ser la primera prioridad. Después de que funciona, evalúa el rendimiento y, si falta, busca formas de mejorarlo, hasta el punto en que sea lo suficientemente bueno.
Hay algunas cosas que debe decidir por adelantado que afectarán el rendimiento; decisiones muy básicas, como qué idioma / tiempo de ejecución utilizará para implementar esta solución. Muchos de estos afectarán el rendimiento en muchos órdenes de magnitud más que llamar un método frente a otro. Honestamente, PHP, como lenguaje con secuencias de comandos, ya es un éxito en el rendimiento, pero como muy pocos sitios con secuencias de comandos se crean de abajo hacia arriba en C / C ++, es comparable a otras tecnologías que probablemente elegiría (Java Servlets, ASP.NET , etc.)
Después de eso, el tamaño del mensaje de E / S es su próximo mayor factor de rendimiento. La optimización de lo que lee y escribe en el disco duro, los puertos serie, las tuberías de red, etc. generalmente mejorará el tiempo de ejecución del programa en muchos órdenes de magnitud, incluso si los algoritmos detrás de las operaciones de E / S fueran eficientes. Después de eso, reduzca la complejidad Big-O del algoritmo en sí, y luego, si es absolutamente necesario, puede "micro-optimizar" eligiendo llamadas a métodos menos costosos y tomando otras decisiones esotéricas a niveles bajos.
fuente
Mencionas que tu papá es un programador retirado. Los programadores que trabajaban en el mundo de mainframe tenían que estar muy preocupados por el rendimiento. Recuerdo haber estudiado una actividad de la Marina de los EE. UU. En la que su computadora central estaba limitada por hardware a 64 KB de memoria por usuario. En ese mundo de programación tienes que buscar cada poquito que puedas.
Las cosas son muy diferentes ahora y la mayoría de los programadores no necesitan preocuparse tanto por las micro optimizaciones. Sin embargo, los programadores de sistemas embebidos todavía lo hacen y las personas de bases de datos todavía necesitan usar código optimizado.
fuente
El código debe estar escrito para ser absolutamente claro sobre lo que hace. Entonces, si y solo si es demasiado lento, retrocede y acelera. El código siempre se puede cambiar para que sea más rápido más tarde, si se puede entender, pero buena suerte cambiándolo para que quede claro si es rápido.
fuente
Es importante si:
1) La vida de alguien depende de tu código. Una función que tarda 25 ms en ejecutarse en el monitor de frecuencia cardíaca de alguien es probablemente una mala idea.
Personalmente, adopto un enfoque doble: hay micro optimizaciones que puede hacer que no afectarán la legibilidad, obviamente desea usarlas. Pero si afecta la legibilidad, espere: no obtendrá muchos beneficios y, en realidad, podría llevarle más tiempo depurar a largo plazo.
fuente
No, dado que hay plataformas como JVM y .NET donde el código está escrito para una máquina virtual y, por lo tanto, tratar de optimizar la ejecución puede no funcionar tan bien como lo que es óptimo en el escritorio de un desarrollador no es necesariamente lo mismo en un servidor. Mire qué tan lejos del hardware están algunas de estas piezas de software de alto nivel para otro punto aquí. Algo a considerar es la diversidad de hardware, ¿qué tan realista es optimizar el código para chips específicos como una CPU o GPU cuando un nuevo modelo probablemente saldrá en menos de un año?
Otra cuestión a considerar aquí es el rendimiento medido por qué métrica: velocidad de ejecución, memoria utilizada en la ejecución, velocidad de desarrollo de nuevas características, tamaño de la base de código en un servidor en formas compiladas o descompiladas, escalabilidad, mantenibilidad, etc. .? Si se toma de manera lo suficientemente amplia, la pregunta se vuelve trivial, pero no estoy seguro de cuán ampliamente quisiste tomar el rendimiento, ya que realmente puede ser casi cualquier cosa, siempre que pueda medirse de alguna manera.
Algunas micro optimizaciones pueden funcionar y otras pueden no funcionar, que es donde uno puede preguntarse cuánto vale la pena realizar dicho trabajo en comparación con otro trabajo que puede considerarse como una prioridad mucho más alta, como nuevas características o corregir errores. La otra pregunta sería si una actualización de hardware o software también puede romper algunas de esas optimizaciones.
fuente
Creo que hay una gran diferencia entre una buena programación y una microoptimización.
Si hay dos formas de hacer la misma tarea, una es más rápida que la otra y ambas tienen la misma legibilidad, debe usar la más rápida. Siempre. Y esta es una buena programación. No hay razón para no usar un mejor algoritmo para resolver un problema. E incluso documentarlo es fácil: proporcione el nombre del algoritmo, todos podrán buscarlo en Google y encontrar más información sobre cómo funciona.
Y buenos algoritmos ya están optimizados. Serán rápidos Serán pequeños Usarán la memoria mínima requerida.
Incluso si los usa su programa todavía no tiene ese rendimiento, puede considerar microoptimizarlo. Y tendrá que conocer realmente el idioma para poder realizar una micro optimización.
Y siempre hay espacio para gastar más dinero en hardware. El hardware es barato, los programadores son caros . No gaste demasiado tiempo / dinero optimizando cuándo puede comprar hardware.
fuente
La legibilidad del código en mi humilde opinión es más importante que la microoptimización porque en la mayoría de los casos la microoptimización no vale la pena.
Artículo sobre micro optimizaciones sin sentido :
Entonces, en la mayoría de los casos, la microoptimización ahorra 1 operación entre millones, pero empeora la legibilidad.
fuente
Otras respuestas son correctas sobre el dinero. Pero agregaré otro punto en el que uno tiene que diferenciar qué es la optimización / microoptimización prematura y escribir código performante que refleje una comprensión del comportamiento de las construcciones del lenguaje / marco (lo siento, no pude encontrar una palabra para el último) . ¡La última es una buena práctica de codificación y generalmente se debe hacer!
Lo explicaré. La mala optimización (lectura de optimización prematura / micro) no es cuando optimiza secciones de código sin crear perfiles para saber si realmente son los cuellos de botella. Es cuando optimiza en función de sus suposiciones, rumores y comportamientos indocumentados. Si está documentado y hace algo de una manera más eficiente / lógica por pequeña que sea, lo llamo buena optimización . Como han dicho otros, ambos tienen inconvenientes y casi no tienen nada de profesionales en lo que respecta a ganar un buen negocio, pero aún así hago lo último, no lo primero, si no vence totalmente la legibilidad. Sí, la legibilidad / mantenibilidad es de suma importancia y se trata de dónde trazar la línea.
Reitero los puntos hechos por otros aquí como la inutilidad de las optimizaciones buenas y malas:
Sus dependencias a un problema específico pueden cambiar y cualquier tiempo dedicado a la optimización antes de completar la sección lógica de su aplicación es una pérdida de tiempo. Me refiero a la optimización en una etapa relativamente temprana. Hoy tiene una
List<T>
y para cuando se envía su aplicación, tenía que cambiarlaLinkedList<T>
y ahora toda la evaluación comparativa era una pérdida de tiempo y esfuerzo.En su mayoría, el verdadero cuello de botella de su aplicación (leída como una diferencia medible) podría ser el 5% de su código (principalmente los sql) y la optimización del otro 95% no brinda a sus clientes ningún beneficio.
Por lo general, el código "técnicamente" de mejor rendimiento significa más verbosidad, lo que a su vez significa más código propenso a errores, lo que a su vez significa una mayor capacidad de mantenimiento y más tiempo invertido, lo que a su vez significa que gana menos dinero.
La huella de carbono que ahorra para todo el mundo a través de una ganancia de rendimiento del 1% se ve fácilmente eclipsada por los gases de efecto invernadero que su equipo tendrá que emitir al depurar y mantener ese código.
Los aspectos negativos de la mala optimización en particular son:
A menudo no te da el rendimiento que esperas. Vea esta pregunta en SO, donde las optimizaciones han fallado . De hecho, puede tener efectos adversos. Ese es el problema con el comportamiento indocumentado.
La mayoría de los compiladores modernos lo harán por usted de todos modos.
Daré algunos ejemplos de optimización buena y mala:
El malo -
uso de tipos enteros más pequeños en lugar de
Int32
.++i
usado en lugar dei++
for
en lugar deforeach
(lo peor que he visto, derrota totalmente la lógica)evitando variables cerradas
usando en
char
lugar de cadena durante la concatenación de cadenas, como:Lo bueno (del mundo .NET. Debe explicarse por sí mismo) -
Doble búsqueda
en lugar de
Cargalos todos
en lugar de
Casting en dos etapas:
en lugar de
Si el orden no importa
en lugar de
Boxeo
en lugar de
Si me pregunta si esto proporciona beneficios de rendimiento notables, le diría que no. Pero sugeriría que uno debería usarlos porque se deriva de una comprensión del comportamiento de estas construcciones. ¿Por qué hacer dos llamadas cuando solo puedes hacer 1? Desde un punto de vista filosófico, es una buena práctica de codificación. Y 1 y 3 también son un poco menos legibles en términos estrictos, pero ¿prevalecen sobre la legibilidad? No, no mucho, así que lo uso. Ahora esa es la clave: mantener una relación de rendimiento a legibilidad decente. Y cuando es eso, se trata de dónde trazas la línea.
fuente
"Vale la pena" necesita contexto, por ejemplo, cuánto más simple es escribir, leer y mantener frente a cuánto más rápido hace que el usuario tenga algo más receptivo, interactivo y requiere menos tiempo para que espere.
Ahorrar unos centavos para comprar una lata de refresco no me hará mucho bien si tengo que viajar una distancia para ahorrar esos centavos, especialmente dado que rara vez bebo refrescos en estos días. Ahorrar unos centavos por lata en una compra de un millón de latas de refresco podría ser un gran problema.
Mientras tanto, ahorro unos centavos cuando dos personas están justo a mi lado y una ofrece exactamente lo mismo por unos centavos más baratos y la otra no, y elijo la más cara porque me gusta más su sombrero parece un caso tonto de pesimismo.
Lo que a menudo encuentro que las personas que llaman "microoptimizaciones" parecen estar curiosamente desprovistas de mediciones, contexto y discusión sobre el usuario final, cuando debería haber absolutamente los tres para considerar tales optimizaciones si no son triviales de aplicar. Para mí, una microoptimización adecuada en estos días se relaciona con cosas como diseños de memoria y patrones de acceso, y aunque pueden parecer "micro" en foco, no son micro en efecto.
Logré, no hace mucho tiempo, reducir una operación de 24 segundos a 25 milisegundos (aproximadamente 960 veces más rápido), con salidas idénticas (aseguradas por pruebas automatizadas), sin cambios en la complejidad algorítmica, para el revestimiento de difusión de calor volumétrico, a través de "micro-optimizaciones" (la mayor de las cuales provino de un cambio en el diseño de la memoria que lo redujo a unos 2 segundos, luego el resto fueron cosas como SIMD y análisis adicionales de errores de caché en VTune y algunos cambios en el diseño de la memoria).
Wolfire explica la técnica aquí, y luchó con el tiempo requerido: http://blog.wolfire.com/2009/11/volumetric-heat-diffusion-skinning/
Mi implementación logró hacerlo en milisegundos mientras luchaba por reducirlo a menos de un minuto:
Después de "microoptimizarlo" de 24 segundos a 25 ms, eso cambió el juego en el flujo de trabajo. Ahora los artistas pueden cambiar sus plataformas en tiempo real a más de 30 FPS sin esperar 24 segundos cada vez que realicen algún pequeño cambio en su plataforma. Y eso realmente cambió todo el diseño de mi software ya que ya no necesitaba la barra de progreso y cosas de este tipo, todo se volvió interactivo. De modo que podría ser una "microoptimización" en el sentido de que todas las mejoras se produjeron sin ninguna mejora en la complejidad algorítmica, pero en efecto fue una "megaoptimización" que hizo lo que antes era un proceso doloroso y no interactivo. en uno interactivo en tiempo real que cambió por completo la forma en que trabajaban los usuarios.
Medición, requisitos del usuario final, contexto
Realmente me gustó el comentario de Robert aquí y tal vez no logré hacer el punto que quería:
Esta es, a pesar de trabajar en un campo muy crítico para el rendimiento con requisitos a menudo en tiempo real, la única vez que considero cualquier micro-optimización que requiera salir de mi camino.
Y enfatizaría no solo las mediciones sino también el lado del usuario final. Soy un bicho raro porque llegué a mi campo actual (y anteriormente gamedev) como usuario / fan primero, desarrollador segundo. Así que nunca me entusiasmaron tanto las cosas habituales que entusiasman a los programadores como resolver acertijos técnicos; Los encontré una carga, pero los soportaría a través del sueño del usuario final que compartí con otros usuarios. Pero eso me ayudó a asegurarme de que si estaba optimizando algo, tendría un impacto real en los usuarios con beneficios reales. Es mi salvaguarda contra la micro-optimización sin rumbo.
En mi opinión, eso es realmente tan importante como el perfilador, porque tenía colegas que hicieron cosas como la subdivisión de micro-optimización de un cubo en mil millones de facetas solo para ahogarse en modelos de producción del mundo real como personajes y vehículos. Su resultado fue impresionante en cierto sentido de "demostración tecnológica", pero casi inútil para los usuarios reales, porque estaban perfilando y midiendo y comparando casos que no se alineaban con los casos de uso del mundo real. Por lo tanto, es muy importante comprender primero lo que es importante para los usuarios, ya sea aprendiendo a pensar y usar el software como tal o colaborando con ellos (idealmente ambos, pero al menos colaborar con ellos).
fuente
isset
vs.strlen
parece más minúsculo en foco ausente el contexto y las medidas. :-DLo diré de esta manera: la microoptimización es un proceso de optimización de algo que no es un cuello de botella. Por ejemplo, si su programa llama a dos funciones A y B, y A tarda 100 milisegundos en completarse y B tarda 2 microsegundos, y sigue optimizando la función B. Eso no solo no es importante, es absolutamente incorrecto. Pero la función de optimización B se llama optimización y no microoptimización. Importancia de la optimización depende. Digamos que no tiene nada más que hacer y su programa está libre de errores, entonces sí, es importante. Pero generalmente tienes prioridades. Digamos que necesita agregar / escribir la función C. Si cree que escribir la función C le dará más dinero que hacer que su programa sea más rápido sin esa funcionalidad, entonces vaya a la optimización. De lo contrario, busque la funcionalidad. También, Los programadores experimentados centrados en el rendimiento no pasan mucho tiempo optimizando, simplemente escriben programas rápidos. Por lo menos saben qué herramientas usar y qué hacer para no pasar años haciendo optimizaciones sin sentido (leer micro).
fuente