Reglas prácticas para la optimización prematura

Parece que la frase ” optimización prematura ” es la palabra de moda del día. Por alguna razón, los progtwigdores de iphone en particular parecen pensar en evitar la optimización prematura como un objective proactivo, en lugar del resultado natural de simplemente evitar la distracción. El problema es que el término comienza a aplicarse cada vez más a casos que son completamente inapropiados.

Por ejemplo, he visto a un número cada vez mayor de personas decir que no deben preocuparse por la complejidad de un algoritmo, porque eso es una optimización prematura (por ejemplo, ayuda para clasificar un NSArray en dos propiedades (con NSSortDescriptor?) ). Francamente, creo que esto es solo pereza y atroz para la informática disciplinada.

Pero se me ocurrió que tal vez, teniendo en cuenta la complejidad y el rendimiento de los algoritmos, vaya por el camino del desenrollado del bucle de ensamblaje y otras técnicas de optimización que ahora se consideran innecesarias.

¿Qué piensas? ¿Estamos en el punto ahora donde la decisión entre un algoritmo de complejidad O (n ^ n) y O (n!) Es irrelevante? ¿Qué pasa con O (n) vs O (n * n)?

¿Qué consideras “optimización prematura”? ¿Qué reglas prácticas usas para evitarlo consciente o inconscientemente?

EDITAR

Sé que mi descripción es un poco general, pero me interesan las reglas prácticas específicas o las mejores prácticas que las personas usan para evitar la “optimización pre-madura”, particularmente en la plataforma de iphone .

Responder a esto requiere que primero responda la pregunta “¿qué es la optimización pre-madura?”. Como esa definición claramente varía mucho, cualquier respuesta significativa requiere que el autor defina el término. Es por eso que realmente no creo que esta sea una pregunta de CW. De nuevo, si las personas no están de acuerdo, lo cambiaré.

    ¿Qué es una optimización prematura?

    La optimización prematura es el proceso de optimización de su código (generalmente para el rendimiento) antes de saber si vale la pena o no hacerlo. Un ejemplo de optimización prematura es optimizar el código antes de que lo hayas perfilado para descubrir dónde está el cuello de botella de rendimiento. Un ejemplo aún más extremo de optimización prematura es la optimización antes de ejecutar su progtwig y establecer que se está ejecutando muy lentamente.

    ¿Estamos en el punto ahora donde la decisión entre un algoritmo de complejidad O (n ^ n) y O (n!) Es irrelevante? ¿Qué pasa con O (n) vs O (n * n)?

    Depende del tamaño de ny de la frecuencia con que se llamará a su código.

    Si n es siempre menor que 5, entonces el rendimiento asintótico es irrelevante. En este caso, el tamaño de las constantes importará más. Un algoritmo simple O (n * n) podría vencer a un algoritmo O (n log n) más complicado para n pequeña. O la diferencia mensurable podría ser tan pequeña que no importa.

    Sigo pensando que hay demasiadas personas que dedican tiempo a optimizar el 90% del código que no importa, en lugar del 10% que lo hace. A nadie le importa si un código tarda 10 ms en lugar de 1 ms si ese código casi nunca se llama. Hay ocasiones en que simplemente hacer algo simple que funciona y seguir adelante es una buena opción, aunque sepas que la complejidad algorítmica no es óptima.

    Cada hora que gasta en optimizar el código rara vez llamado es de una hora menos que puede gastar en agregar las características que la gente realmente quiere.

    Mi voto va para que la mayoría de las personas optimice lo que creen que es el punto débil, pero no lo hacen.

    Por lo tanto, independientemente de qué tan bien conozca los algoritmos y sin importar qué tan bien haya escrito su código, no sabrá qué más sucede fuera de su módulo. ¿Qué hacen las API que llamaste detrás de escena? ¿Puedes garantizar siempre que el orden particular de las operaciones es el más rápido?

    Esto es lo que significa Optimización Prematura. Cualquier cosa que piense que es una optimización que no ha sido probada rigurosamente por medio de un perfilador u otra herramienta definitiva (ciclos de reloj por operación no es malo, pero solo le dice características de rendimiento ~ las llamadas reales son más importantes que el tiempo, generalmente ), es una optimización prematura.

    @k_b lo dice muy bien, y es lo que digo también. Hazlo bien, hazlo simple, luego haz un perfil y luego modifica. Repita según sea necesario.

    Orden de prioridad: 1. Tiene que funcionar 2. Tiene que ser mantenible 3. Tiene que ser eficiente en la máquina

    Eso fue desde la primera semana de mi primer curso de progtwigción. En 1982

    La “optimización prematura” es cualquier momento en que se haya considerado la Prioridad 3 antes de la Prioridad 1 o 2.

    Tenga en cuenta que las técnicas de progtwigción modernas (abstracciones e interfaces) están diseñadas para facilitar esta priorización.

    El único área gris: durante el diseño inicial, debe verificar que sus soluciones no sean intrínsecamente lentas. De lo contrario, no se preocupe por el rendimiento hasta que al menos tenga algún código de trabajo.

    Para algunas personas, la optimización es parte de la diversión de escribir código, prematuro o no. Me gusta optimizar y contenerme por la legibilidad. El consejo de no optimizar tanto es para las personas que les gusta optimizar.

    Los progtwigdores de iphone en particular parecen pensar en evitar la optimización prematura como un objective proactivo

    La mayoría del código de iPhone está relacionado con la interfaz de usuario. No hay mucha necesidad de optimizar. Existe la necesidad de no elegir un diseño deficiente que dé como resultado un mal rendimiento, pero una vez que comience a codificar un buen diseño, hay poca necesidad de optimización. Entonces, en ese contexto, evitar la optimización es un objective razonable.

    ¿Qué consideras “optimización prematura”? ¿Qué reglas prácticas usas para evitarlo consciente o inconscientemente?

    El uso del enfoque ágil (iteraciones rápidas con refinamiento de requisitos a través de interacciones con usuarios) es útil ya que la conciencia de que la interfaz actual probablemente va a cambiar drásticamente después de la próxima sesión con los usuarios hace que sea más fácil enfocarse en desarrollar las características esenciales del aplicación en lugar del rendimiento.

    De lo contrario, algunas iteraciones en las que pasó mucho tiempo optimizando una característica que se descartó completamente después de la sesión con el usuario deberían darle el mensaje.

    La complejidad del algoritmo, e incluso la elección, es un problema que debe ocultarse detrás de una interfaz. Por ejemplo, una Lista es una abstracción que se puede implementar de varias maneras con diferentes eficiencias para diferentes situaciones.

    A veces, evitar la optimización prematura puede ayudar al diseño, porque si diseñas con la idea de que necesitarás optimizar más adelante, entonces estás más inclinado a desarrollar en el nivel abstracto (por ejemplo, lista) en lugar del nivel de implementación (por ej., Matriz o lista enlazada) .

    Esto puede dar como resultado un código más simple y legible, además de evitar la distracción. Si se progtwig en la interfaz, las diferentes implementaciones se pueden intercambiar posteriormente para optmizar. La optimización prematura lleva al riesgo de que los detalles de la implementación se expongan prematuramente y se combinen con otros componentes de software que no deberían ver estos detalles.

    ¿Qué reglas prácticas usas para evitarlo consciente o inconscientemente?

    Una forma de evitar la optimización innecesaria es considerar el beneficio de costo relativo:

    A) Costo para que el progtwigdor optimice el código + costo para probar dicha optimización + costo de mantener un código más complejo como resultado de dicha optimización

    vs.

    B) Costo para actualizar el servidor en el que se ejecuta el software o simplemente comprar otro (si es escalable)

    Si A >> B considera si es lo correcto. [Ignorando por el momento el costo ambiental de B que puede o no ser una preocupación para su organización]

    Esto se aplica de manera más general que solo a una optimización prematura, pero puede ayudar a inculcarles a los desarrolladores la sensación de que gastar su tiempo haciendo trabajos de optimización es un costo y no debe realizarse a menos que exista una diferencia real mensurable en algo realmente importante : número de servidores requeridos o la satisfacción del cliente a través de tiempos de respuesta mejorados.

    Si la gerencia no puede ver el beneficio en $ reducido y los clientes no pueden ver el beneficio en mejores tiempos de respuesta, pregúntese por qué lo está haciendo.

    Creo que esta es una cuestión de sentido común. Es necesario comprender el outlook general, o incluso lo que sucede bajo el capó, para poder considerar cuándo está justificado un movimiento llamado “prematuro”.

    He trabajado con soluciones donde las llamadas al servicio web eran necesarias para calcular nuevos valores basados ​​en el contenido de una lista local. La forma en que esto se implementó fue haciendo una solicitud web por valor. No sería una optimización prematura enviar varios valores a la vez. Lo mismo ocurre con el uso de transacciones de base de datos para operaciones múltiples, es decir, insertos múltiples.

    Cuando se trata de algoritmos, inicialmente lo más importante es hacerlo bien y lo más simple posible. Preocuparse por los problemas de stack vs. montón en ese punto sería una locura.