2009-02-05 14 views
12

Me parece darse cuenta de dos escuelas de pensamiento emergentes en lo que respecta a la optimización:Planificación para la eficiencia temprana vs optimización prematura

  1. optimización prematura es la raíz de todo mal. Solo debe optimizar cuando haya escrito lo más fácil y lo más simple posible. Si después del perfilado determina que el software es demasiado lento, debe optimizarlo.
  2. Las optimizaciones deben realizarse al principio del ciclo de vida de un proyecto. Las optimizaciones deben planificarse, pero deben hacerse razonablemente.

En la cara de las cosas, parecen ser puntos de vista bastante opuestos. El caso es que veo el mérito en ambas escuelas de pensamiento. También puedo pensar en momentos en que estas dos formas de pensar me han ayudado a escribir un software mejor y más rápido.

¿Hay alguna forma de conciliar estas dos ideas? ¿Hay un término medio? ¿Hay un momento en que una idea es la mejor herramienta para el trabajo? ¿O estoy presentando una falsa dicotomía y ambos puntos de vista pueden coexistir pacíficamente?

+1

posible duplicado de [Cuándo debe empezar la optimización de código?] (Http://stackoverflow.com/questions/178045/when-should-you-start-optimising-code) –

Respuesta

9

Lo que suelo hacer es aplicar esas optimizaciones que no me cuestan nada (o casi nada). También estoy atento a los algoritmos que no se escalan bien y se llaman con mucha frecuencia. Aparte de eso, no optimizo hasta que el software se ejecuta y tengo la oportunidad de iniciar el generador de perfiles. Solo entonces invertiré un tiempo serio en la optimización.

+1

1 - Grandes + reglas simples –

1

Yo diría que el punto medio sería tener en cuenta las ineficiencias conocidas cuando se está escribiendo código, pero no optimizarlo anticipadamente si significaría tiempo adicional en el desarrollo inicial o complejidad añadida.

Mi teoría es: "Escriba código de trabajo simple, luego optimícelo según lo requiera la prueba".

27

Optimice desde el principio el nivel de diseño y arquitectura. Micro-optimizar en el nivel de implementación más tarde.

Debe ser consciente de los costos de rendimiento de las decisiones de diseño que tome y que será difícil cambiar más tarde. La implementación a menudo se puede ajustar más adelante, por lo que no vale la pena hacerlo hasta que sepa que es un problema.

+0

I Me gustaría agregar que la micro-optimización solo debe hacerse después de medir el rendimiento y solo en los cuellos de botella de rendimiento. – Mendelt

+0

Mendelt: Absolutamente :) –

+0

Esta es probablemente la mejor respuesta. Pero pensé que le daría a alguien con un poco menos representante. –

1

Debe ser puramente un análisis de retorno de la inversión. Si puede poner un poco de esfuerzo en la optimización del diseño y obtener un gran retorno en el rendimiento, hágalo. Gradualmente llegarás al punto en el que el retorno por la cantidad de esfuerzo ya no tiene sentido.

4

Concéntrese en la escritura de código que hace exactamente lo que se supone que debe hacer, y solo el número de veces requerido. La optimización del código limpio y elegante suele ser simple.

2

Me gusta la formulación de this guy.

  1. optimización mediante el uso de un enfoque global sensata más .
  2. Optimización haciendo que el código sea menos raro.
  3. Optimización haciendo que el código sea más extraño.

Los dos primeros son apuntas 2. Su 3 es el 1 y el que es la raíz de todo mal. Y tiene razón, las optimizaciones que hacen que el código sea "más extraño" lo hacen más complicado y más difícil de entender, lo que resulta en más errores y dolores de cabeza por mantenimiento.

1

Hay una verdad básica:

No se puede optimizar lo que no se puede probar

Por lo tanto, como otros han dicho, y especialmente WRT a optimizaciones de rendimiento, se debe escribir el código a continuación, ser capaz de probarlo. Sin embargo, en un gran cuerpo de código, un algoritmo puede ser el más rápido, pero dado que se relaciona con otro código, es una optimización inútil que le cuesta tiempo, o es más lento que la opción 2, 3. ..

Sin embargo, existe un cuerpo de conocimiento que puede aprovechar, especialmente en el nivel conceptual, que puede ayudarlo a "preoptimizar" su diseño a escala global.

Lamentablemente, este es uno de esos debates que no tiene un cierre real.

4

Lo ideal es primero perfilar, luego optimizar cuando sea necesario, pero eso no funciona con el diseño; para cuando tenga algo ejecutable para el perfil, cambiar el diseño sería muy costoso. Por lo tanto, el diseño debe prestar atención a la eficiencia por adelantado. Por lo general, esto significa esbozar algoritmos eficientes por adelantado y mantener la flexibilidad suficiente para cambiar más tarde. (Esto a menudo se realiza mejor con una buena separación de funciones, manteniendo los módulos tan independientes como sea posible, y eso es una buena práctica de diseño por otras razones).

Normalmente, en la (s) fase (s) de diseño, tendrá una buena idea qué tan importante es el rendimiento Si es necesario, puede diseñar desde el principio el rendimiento (que no incluye optimizaciones a nivel de código).

También está el desarrollo de hábitos de codificación eficientes al elegir entre dos prácticas similares. Por ejemplo, en C++ vale la pena escribir ++i en lugar de i++, porque es algo trivial que a veces puede ser significativamente más eficiente.

Cualquier cosa más que eso debe esperar hasta que (a) quede claro que mejorar el rendimiento dará sus frutos, y (b) usted sabe dónde están los puntos de acceso.

2

También tendría: Utilice estructuras de datos adecuadas y eficientes desde el inicio. Esto cubre una amplia gama de cosas:

  1. Conozca cómo funcionan todos los contenedores estándar, en qué son buenos y en qué son malos. p.ej. SortedDictionary es rápido en la inserción y búsqueda, pero deficiente en la eliminación. LinkedList es rápido de agregar y eliminar, pero deficiente en la búsqueda, etc.
  2. Sepa dónde estarán sus cuellos de botella. ¿Será CPU, disco, memoria, gráficos, IO, redes, etc. Sepa cómo utilizar cada uno de manera eficiente, cada área requiere diferentes patrones de diseño. Esto realmente depende de la aplicación que se desarrolle también: ¿cuál es la métrica central para concentrarse, para la capacidad de respuesta de la interfaz de usuario, para el buen procesamiento de datos del almacenamiento en caché de disco.
  3. Multhreading. Si la aplicación se escalará a múltiples núcleos, debe decidirse muy temprano en el ciclo de vida de desarrollo si se necesita dicho sistema.El enhebrado en una etapa posterior es mucho más costoso.

Algunas de las respuestas que sabrá por experiencia, algunas requerirán investigación, pero nunca será un trabajo de adivinanza.

1

Las bases de datos en particular no son fáciles de refactorizar y suelen ser el mayor cuello de botella en el sistema debido a los diseñadores que piensan que no deberían preocuparse por el rendimiento cuando diseñan. Esto es miope Hay muchas optimizaciones de bases de datos conocidas que casi siempre serán más rápidas. No utilizarlos en su diseño y codificación inicial para evitar una "optimización prematura" es una tontería. Por ejemplo, un cursor casi nunca (a menos que busque totales en ejecución) rinde mejor que una consulta basada en conjunto en SQl Server. Escribir un cursor en lugar de una consulta basada en conjuntos no es más rápido (una vez que comprende las consultas basadas en conjuntos), por lo que no hay ninguna razón para comenzar con el código basado en el cursor. Lo mismo con las subconsultas de vicevías de tablas derivadas. ¿Por qué escribir el código que usted sabe el 90% del tiempo será más lento que otro código que toma la misma cantidad de tiempo para escribir?

Elegir usar una herramienta que lo dificulta más tarde para la melodía de rendimiento también es una decisión miope, por lo que al considerar cómo pretende acceder a la base de datos, esto debería ser parte de lo que considera.

Cualquiera que codifique contra una base de datos o que los diseñe, debe tomarse el tiempo para leer sobre el ajuste del rendimiento para su tipo particular de base de datos. Saber de antemano cómo escribir una consulta detectable y qué tipo de cosas deberían tener los índices con los que empiezas y cuáles son los tipos habituales de cuellos de botella te ayudará a hacer el trabajo mejor la primera vez.

+0

No es difícil refacturar una base de datos, suponiendo que haya realizado algunos pasos iniciales (como usar principalmente vistas y desaprobar el acceso directo a la tabla tanto como sea posible) y tener un sistema para refactorizar en vuelo. Ver http://www.agiledata.org/essays/databaseRefactoring.html para más. – alphadogg

+0

Lamentablemente, muy pocas bases de datos existentes están diseñadas de esta manera. Estoy de acuerdo en que es bueno considerar la refactorización en el diseño, pero de cientos de bases de datos que tuve que consultar (solía trabajar para una agencia de auditoría y tuve que mirar el diseño de muchas bases de datos). No he visto uno que haya sido diseñado. camino. – HLGEM

3

Adaptación de la cita "es la táctica si gana y es trampa si se pierde", diría

Se trata de "planificación de la eficiencia" si ha funcionado y es "optimización prematura" si didn' t.

1

Aquí es donde la planificación entra en juego. Si tiene un gran plan y tiene un buen modelo para lo que está escribiendo, la optimización solo debería tener lugar en la publicación. Si te encuentras que necesitas optimizar mucho tu código, lo más probable es que estés haciendo algo incorrectamente para empezar.

Mucho de esto también vendrá con experiencia y trabajando en tareas similares. En general, la única vez que debe escribir algo que debe optimizarse es cuando está cubriendo cosas con las que nunca antes trabajó. Las optimizaciones suceden en la fase de planificación y en la fase posterior al proyecto IMO.

2

Constrúyalo lo mejor que pueda la primera vez sin agregar mucho tiempo o esfuerzo. Entonces déjalo luchar por tu atención.

1

El código, además de proporcionar proporcionando la functioanlity básica, tiene tres más característica que el desarrollador de software necesita proporcionar:

  1. Rendimiento
  2. mantenibilidad
  3. Robustez

Un código de reposo proporcionaría los tres de estos. con recursos limitados, la llamada de qué parte del código debe optimizarse para lo que debe evaluarse. La optimización de uno de estos, a costa de los demás, es peligrosa, y debe ser evitada en la medida de lo posible.

+0

Supongo que no necesariamente en ese orden, ¿verdad? :-) –

+0

true. Creo que debería ser el orden inverso exacto ... – vrdhn

Cuestiones relacionadas