2009-03-31 6 views
10

Uno de los mantras más comunes en informática y programación es nunca optimizar de forma prematura, lo que significa que no debe optimizar nada hasta que se haya identificado un problema, ya que la legibilidad del código/mantenibilidad es probable que sufra.¿Qué optimizaciones están bien para hacer de inmediato?

Sin embargo, a veces puede saber que una forma particular de hacer las cosas tendrá un bajo rendimiento. ¿Cuándo está bien optimizar antes de identificar un problema? ¿Qué tipo de optimizaciones son permisibles desde el principio?

Por ejemplo, usando el menor número de conexiones de base de datos como sea posible, y prestando mucha atención a que, si bien el desarrollo, en lugar de utilizar una nueva conexión, según sea necesario y preocuparse por el costo de rendimiento después

+0

Wiki de la comunidad? –

+0

En su ejemplo, tener el bucle invariante dentro del bucle es una práctica de programación deficiente, y debe estar bien documentado por qué está dentro del bucle para los pocos casos de excepción en que podría ser necesario. – Elie

Respuesta

26

Creo que se está perdiendo el sentido de ese dicho. No hay nada malo en hacer algo de la manera más eficiente posible desde el principio, proporcionado También es claro, sencillo, etc.

El punto es que usted no debe atarse (y peor, su código) en nudos tratando de resolver problemas que ni siquiera pueden existir Ahorre ese nivel de optimizaciones extremas, que a menudo son costosas en términos de desarrollo, mantenimiento, deuda técnica, zonas de reproducción de errores, portabilidad, etc. para los casos en que realmente lo necesitan.

3

Si usted no tiene una problema de rendimiento, entonces no debe sacrificar la legibilidad por el rendimiento. Sin embargo, al elegir una forma de implementar alguna funcionalidad, debe evitar el uso de un código que sepa que es problemático desde el punto de vista del rendimiento. Entonces, si hay 2 formas de implementar una función, elija la que probablemente tenga un mejor rendimiento, pero si no es la solución más intuitiva, asegúrese de incluir algunos comentarios sobre por qué la codificó de esa manera.

14

Creo que estás viendo esto de la manera incorrecta. El objetivo de evitar la optimización prematura no es evitar la optimización, es evitar la mentalidad en la que puede caer.

Escribe tu algoritmo de la manera más clara que puedas primero. Entonces asegúrate de que sea correcto. Entonces (y solo entonces) se preocupe por el rendimiento. Pero también piense en mantenimiento, etc.

Si sigue este enfoque, su pregunta se responde a sí misma. Las únicas "optimizaciones" que son permisibles desde el principio son aquellas que son al menos tan claras como el enfoque directo.

+0

En segundo lugar ... Si pudiera darle más de 10 votos, lo haría ... –

4

En mi humilde opinión, ninguna. Escribe tu código sin pensar en "optimización". En su lugar, piense en "claridad", "corrección", "mantenimiento" y "comprobabilidad".

+0

Por supuesto ... Considero cada una de esas optimizaciones. :) – Randolpho

+0

Bueno, eso está bien si está desarrollando un sitio web o GUI, pero apostaría que los programadores de sistemas integrados no estarían de acuerdo con usted. –

+0

@ed - sus habilidades psíquicas le han fallado - yo no hago sitios web o GUI. –

-2

No llame a Collection.ElementCount directamente en la expresión de comprobación de bucle si está seguro de que este valor se calculará en cada pase.

En lugar de:

for (int i = 0; i < myArray.Count; ++i) 
{ 
    // Do something 
} 

Do:

int elementCount = myArray.Count; 
for (int i = 0; i < elementCount ; ++i) 
{ 
    // Do something 
} 

Un caso clásico.

Por supuesto, debe saber qué tipo de colección es (en realidad, cómo se implementa la propiedad/método Count). Puede que no sea necesariamente costoso.

+0

Hmm. ¿No es la optimización real no poner las cosas que se calculan en cada pase en una propiedad? Hazlo una función y quedará claro. – Jerph

+0

Nunca he escuchado hablar de ese enfoque en realidad ... Sin embargo, la gente no tendrá la idea de que incluso llamar a un método en un bucle podría ser malo. – User

+0

Estoy dispuesto a apostar que la mayor parte del tiempo/conteo de una matriz/colección es una operación O (1). Entonces tendría que estar en desacuerdo. –

6

La mejor optimización que puede hacer en cualquier tiempo es elegir el algoritmo correcto para el problema. Es sorprendente la frecuencia con la que un poco de pensamiento produce un mejor enfoque que ahorrará órdenes de magnitud, en lugar de un pequeño porcentaje. Es una victoria completa.

Las cosas a buscar:

  • Fórmulas matemáticas en lugar de iteración.
  • Patrones que son bien conocidos y documentados.
  • código/componentes existentes
2

A medida que desarrolla en su carrera como desarrollador, que simplemente va a crecer en la conciencia de los mejores enfoques, más razonables a los distintos problemas. En la mayoría de los casos que puedo pensar, el trabajo de mejora del rendimiento dio como resultado un código que era en realidad más pequeño y más simple que algún enredo complejo que evolucionó desde el trabajo a través de un problema. A medida que mejora, estas soluciones más simples y rápidas se vuelven más sencillas y más naturales de generar.

Actualización: Estoy votando +1 por cada uno en el hilo hasta ahora porque las respuestas son tan buenas. En particular, DWC ha capturado la esencia de mi posición con algunos maravillosos ejemplos.

2

Documentación

La documentación de su código es el # 1 de optimización (del proceso de desarrollo) que se puede hacer desde el principio. A medida que crecen, los proyectos más personas que interactúan con y entre más gente tiene que entender lo que ha escrito, cuanto más tiempo se gastará

Herramientas

Asegúrese de que su caja de herramientas es adecuado para la aplicación que estés desarrollando. Si está haciendo una aplicación pequeña, no hay razón para invocar el poderoso poder de un sistema GUI basado en Eclipse.

Complilers

dejar que el compilador hacer el trabajo duro. La mayoría de las veces, la optimización cambia a un compilador y hará la mayoría de las cosas importantes que necesita.

Sistema optimizaciones específicas

Especialmente en el mundo embebido, obtener una comprensión de la arquitectura subyacente de la CPU y el sistema que está interactuando. Por ejemplo, en una CPU Coldfire, puede obtener grandes mejoras de rendimiento al garantizar que sus datos se encuentren en el límite de bytes adecuado.

Algoritmos

esforzamos para que los algoritmos de acceso O (1) o O (log n). Esfuércese por hacer una iteración sobre una lista no más que O (N). Si está tratando con grandes cantidades de datos, evite algo más que O (N^2) si es posible.

trucos Código

evitar, si es posible.Esta es una optimización en sí misma: una optimización para hacer que su aplicación sea más fácil de mantener a largo plazo.

0

De acuerdo con Neil's opinion aquí, realizar optimizaciones de rendimiento en el código de inmediato es una mala práctica de desarrollo.

IMHO, La optimización del rendimiento depende del diseño de su sistema. Si su sistema ha sido diseñado de manera deficiente, desde el punto de vista del rendimiento, ninguna cantidad de optimización de código le dará un "buen" rendimiento: puede obtener un rendimiento relativamente mejor, pero no un buen rendimiento. Por ejemplo, si se pretende construir una aplicación que acceda a una base de datos, un modelo de datos bien diseñado, que haya sido desnormalizado lo suficiente, si es probable que produzca mejores características de rendimiento que su contrario, un modelo de datos mal diseñado. que ha sido optimizado/ajustado para obtener un rendimiento relativamente mejor.

Por supuesto, uno no debe olvidar los requisitos en esta mezcla. Existen requisitos de rendimiento implícitos que se deben tener en cuenta durante el diseño: el diseño de un sitio web público requiere a menudo que se reduzcan los viajes del lado del servidor para garantizar una sensación de "alto rendimiento" para el usuario final. Eso no significa que reconstruyas el DOM en el navegador en cada acción y repintes el mismo (he visto esto en realidad), sino que reconstruyes una parte del DOM y dejas que el navegador haga el resto (lo que habría ha sido manejado por un diseñador sensato que entendió los requisitos implícitos).

4

de Wikipedia:

Debemos olvidarnos de pequeñas eficiencia, dicen que alrededor del 97% de las veces : la optimización prematura es la raíz de todo mal. Sin embargo, no deberíamos perder nuestras oportunidades en ese crítico 3%. - Donald Knuth

Creo que lo resume todo. La pregunta es saber si estás en el 3% y qué camino tomar. Personalmente ignoro la mayoría de las optimizaciones hasta que al menos mi código funcione. Por lo general, como un pase por separado con un generador de perfiles, así puedo asegurarme de que estoy optimizando las cosas que realmente importan. Muchas veces el código simplemente funciona lo suficientemente rápido como para que todo lo que hagas tenga poco o ningún efecto.

0

Escogiendo las estructuras de datos apropiadas. Ni siquiera estoy seguro de que tenga en cuenta la optimización, pero puede afectar la estructura de su aplicación (por lo tanto, es bueno hacerlo desde el principio) y aumentar en gran medida el rendimiento.

1

Debe evitar todas las optimizaciones si la única creencia de que el código que está optimizando será lento. El único código que debe optimizar es cuando sabe que es lento (preferiblemente a través de un generador de perfiles).

Si se escribe clara y fácil de entender el código entonces las probabilidades son que va a ser lo suficientemente rápido, y si no lo es entonces cuando se va a acelerarlo Debería ser más fácil de hacer.

Dicho esto, debe aplicar el sentido común (!). ¿Debería leer un archivo una y otra vez o debería almacenar en caché los resultados? Probablemente almacenar en caché los resultados. Entonces, desde el punto de vista de la arquitectura de alto nivel, debería pensar en la optimización.

La parte "mal" de optimización es el "pecados" que se cometen en nombre de hacer algo más rápido - esos pecados generalmente resultan en el código que es muy difícil de entender. No estoy 100% seguro de que este sea uno de ellos ..pero mira this question here, esto puede o no ser un ejemplo de optimización (podría ser la forma en que la persona pensó hacerlo), pero hay formas más obvias de resolver el problema que las elegidas.

Otra cosa que puede hacer, lo cual hice recientemente, es cuando está escribiendo el código y necesita decidir cómo hacer algo. Escríbalo en ambos sentidos y ejecútelo a través de un generador de perfiles. A continuación, elija la forma más clara de codificarlo a menos que haya una gran diferencia en velocidad/memoria (dependiendo de lo que busque). De esta forma, no está adivinando qué es "mejor" y puede documentar por qué lo hizo de esa manera para que alguien no lo cambie más adelante.

El caso que estaba haciendo era usar archivos mapeados en memoria -vs-stream I/O ... el archivo mapeado en memoria era significativamente más rápido que en el otro sentido, así que no estaba preocupado si el código era más difícil de seguir (no lo fue) porque la aceleración fue significativa.

Otro caso que tuve fue la decisión de "internar" String en Java o no. Hacerlo debería ahorrar espacio, pero a un costo de tiempo. En mi caso, el ahorro de espacio no fue enorme, y el tiempo fue doble, así que no hice el internado. Documentarlo le permite a otra persona saber que no se moleste en internarlo (o si quieren ver si una versión más nueva de Java lo hace más rápido, entonces pueden intentarlo).

1

Además de ser claro y sencillo, también debe tomarse un tiempo razonable para implementar el código correctamente. Si le toma un día lograr que el código funcione correctamente, en lugar de las dos horas que habría tomado si lo hubiera escrito, entonces posiblemente haya perdido el tiempo que podría haber gastado en arreglar el rendimiento real problema (Knuth's 3%).

Cuestiones relacionadas