2009-01-28 51 views
8

Me pregunto qué tipo de técnicas de optimización las personas utilizan a menudo hoy en día. He visto gente haciendo caché todo el tiempo con diccionario y todo. ¿Es el espacio de negociación de la velocidad el único camino a seguir?Técnicas de optimización en C#

+0

¿Puede ser más específico sobre el escenario que tiene en mente? La "optimización" es una categoría terriblemente amplia. – Larsenal

+0

Sí, camino a lo ancho. ¿Tienes una pregunta específica? –

+0

Solo me pregunto si hay alguna forma de optimizar el código que no sea el uso del almacenamiento en caché con diccionarios. – Tom

Respuesta

2

Depende de muchas cosas, de verdad.

Como ejemplo, cuando la memoria se convierte en un problema y se crean muchos objetos temporales, tiendo a usar grupos de objetos. (Tener un recolector de basura no es una razón para no ocuparse de la asignación de memoria). Si la velocidad es lo que importa, entonces podría usar punteros inseguros para trabajar con matrices.

De cualquier manera, si te encuentras luchando demasiado con las técnicas de optimización en una aplicación C# /. Net, probablemente elijas un idioma/plataforma equivocado.

1

En general, asegúrese de comprender la complejidad de tiempo de los diferentes algoritmos, y use ese conocimiento para elegir sus implementaciones con prudencia.

Para .NET en particular, este artículo entra en gran detalle sobre la optimización del código implementado en el CLR (aunque también es relevante para Java o cualquier otra plataforma moderna), y es una de las mejores guías que he leído :

http://msdn.microsoft.com/en-us/library/ms973852.aspx

para destilar el artículo en una frase: Nada afecta a la velocidad de una aplicación .NET (con algoritmos sensibles) más que la memoria de la huella de sus objetos. Tenga mucho cuidado para minimizar su consumo de memoria.

4

A menudo también hay problemas con los algoritmos, generalmente cuando se hace algo costoso dentro de un ciclo. En general, lo primero que debe hacer es perfilar su aplicación, que le indicará la (s) parte (s) más lenta (s) de la aplicación. En general, lo que hace para acelerar su aplicación depende de lo que encuentre. Por ejemplo, si su aplicación imita un sistema de archivos, es posible que llame a la base de datos recursivamente para viajar por el árbol (por ejemplo). Puede optimizar ese caso cambiando esas llamadas recursivas en una llamada de base de datos aplanada que devuelve todos los datos en una sola llamada.

Nuevamente, la respuesta es, como siempre, 'depende'. Sin embargo, más ejemplos y consejos se pueden encontrar en Rico Mariani's blog (hojee algunos años, ya que su enfoque ha cambiado):

+0

El perfil de su aplicación específica es probablemente el único buen consejo. Perfil, vea qué es lento (o acapara la memoria) y trate de cortarlo. – Kibbee

+0

Realmente estoy buscando buenos ejemplos. La gente usa la memorización (almacenamiento en caché de nuevo) para las recursiones. +1 para el ejemplo de la base de datos. – Tom

3

Realmente se trata de su elección en algoritmos. Por lo general, no hay una "bala de plata" para la optimización.

Por ejemplo, usar un StringBuilder en lugar de concatenación puede hacer que su código sea significativamente más rápido, pero hay una compensación. Si no está concatenando grandes conjuntos de cadenas, la memoria y el tiempo necesarios para inicializar StringBuilder es peor que el simple uso de concatenación regular. Hay muchos ejemplos de esto en todo el marco, como el almacenamiento en caché del diccionario como mencionaste en tu pregunta.

La única optimización general que puede realmente aprender y aplicar a su codificación a lo largo de su día es el rendimiento alcanzado por el boxeo/unboxing (montón vs. pila). Para hacer esto, debe aprender de qué se trata y cómo evitar o reducir la necesidad de hacerlo.

La documentación de MSDN de Microsoft tiene 2 artículos sobre el rendimiento que ofrecen muchas buenas técnicas de uso general (en realidad son solo versiones diferentes del mismo artículo).

+0

StringBuilder es un optimizador increíblemente fácil de implementar cuando se trabaja con construcción iterativa. – Pat

1

recomendaría efectiva C# por Bill Wagner (first edition y second edition). Pasa por una serie de construcciones y técnicas de lenguaje y explica cuáles son más rápidos y por qué. Él toca muchas mejores prácticas también.

Sin embargo, la mayoría de las veces, la optimización de su algoritmo le dará mejores resultados que el uso de cualquier tipo de lenguaje/técnica de optimización.

+0

Exactamente lo que hubiera dicho, aquí es donde iría en mi primer pase. – mmr

2

voy a sugerir a continuación

1. Saber cuándo utilizar StringBuilder

Usted debe haber oído antes de que un objeto StringBuilder es mucho más rápido al concatenar cadenas juntos que los tipos normales de cadenas.

The thing is StringBuilder is faster mostly with big strings. This means if you have a loop that will add to a single string for many iterations then a StringBuilder class is definitely much faster than a string type. However if you just want to append something to a string a single time then a StringBuilder class is overkill. A simple string type variable in this case improves on resources use and readability of the C# source code.

Basta con elegir correctamente entre objetos StringBuilder y tipos de cadenas se puede optimizar el código.

2. La comparación de cadenas no entre mayúsculas y minúsculas

en una aplicación a veces es necesario comparar dos variables de cadena, haciendo caso omiso de los casos. El enfoque tentadora y tradicionalmente es convertir a ambas cadenas en minúsculas o en mayúsculas y luego compararlos, como por ejemplo:

str1.ToLower() == str2.ToLower()

Sin embargo repetidamente llamar a la función ToLower() es un cuello de botella en el performace. Al usar la función incorporada string.Compare(), puede aumentar la velocidad de sus aplicaciones.

Para comprobar si dos cadenas son iguales ignorando caso se vería así:

string.Compare(str1, str2, true) == 0 //Ignoring cases

La función C# string.Compare devuelve un entero que es igual a 0 cuando las dos cadenas son iguales.

3. Uso String.Empty

Esto no es tanto una mejora del rendimiento, ya que es una mejora la legibilidad, pero todavía cuenta como la optimización del código. De tratar de reemplazar líneas como:

if (str == "")

con:

if (str == string.Empty)

Esto es simplemente una mejor práctica de programación y no tiene impacto negativo en el rendimiento.

Tenga en cuenta que existe una práctica popular que comprobar que la longitud de una cadena sea 0 es más rápida que compararla con una cadena vacía. Si bien eso podría haber sido cierto una vez que ya no es una mejora significativa en el rendimiento. En cambio, quédate con la cuerda. Vacío.

4. Reemplazar con ArrayList Lista <>

ArrayList son útiles al almacenar múltiples tipos de objetos dentro de la misma lista. Sin embargo, si mantiene el mismo tipo de variables en una ArrayList, puede obtener un aumento de rendimiento utilizando los objetos List <> en su lugar.

tomar las siguientes ArrayList:

ArrayList intList = new ArrayList(); 
intList.add(10); 
return (int)intList[0] + 20; 

Aviso que sólo contiene números enteros. Usar la clase List <> es mucho mejor. Para convertirla en una lista escrita a máquina, solamente los tipos de variables necesitan ser cambiados:

List<int> intList = new List<int>(); 

intList.add(10) 

return intList[0] + 20; 

No hay necesidad de emitir tipos con la lista <>. El aumento del rendimiento puede ser especialmente significativo con tipos de datos primitivos como los enteros.

5. Utilice & & y || operadores

Cuando la construcción de si las declaraciones, simplemente asegúrese de usar la notación de doble y (& &) y/o el doble o anotación (||), (en Visual Basic son AndAlso y OrElse).

Si las declaraciones que usan & y | debe verificar cada parte de la declaración y luego aplicar el "y" o "o". Por otro lado, & & y || revise las declaraciones de a una por vez y deténgase tan pronto como se cumpla la condición o no se cumplan.

Ejecución menos código es siempre un beneficio performace, sino que también puede evitar los errores de tiempo de ejecución, considere el siguiente código C#:

if (object1 != null && object1.runMethod()) 

Si objeto1 es nulo, con la & & operador, object1.runMethod () no se ejecutará. Si el operador & & se reemplaza por &, object1.runMethod() se ejecutará incluso si ya se sabe que el objeto1 es nulo, lo que causa una excepción.

6. inteligente Try-Catch

declaraciones try-catch tienen el propósito de capturar las excepciones que están fuera del control de los programadores, como conectarse a la web o un dispositivo, por ejemplo. El uso de una instrucción try para mantener el código "simple" en lugar de utilizar sentencias if para evitar llamadas propensas a errores hace que el código sea increíblemente más lento. Reestructurar su código fuente para requerir menos declaraciones de prueba.

7. Reemplazar Divisiones

C# es relativamente lento cuando se trata de operaciones de división. Una alternativa es reemplazar divisiones con una operación de multiplicación-cambio para optimizar aún más C#.El artículo explica en detalle cómo hacer la conversión.

REFERENCE