2010-08-02 14 views
11

es la siguiente:¿Declarar una variable dentro/fuera de un bucle cambia el rendimiento?

foreach(Type item in myCollection) 
{ 
    StringBuilder sb = new StringBuilder(); 
} 

mucho más lento que:

StringBuilder sb = new StringBuilder(); 

foreach(Type item in myCollection) 
{ 
    sb = new StringBuilder(); 
} 

En otras palabras, ¿realmente importa donde yo anuncio mi StringBuilder?

+3

Similar a http://stackoverflow.com/questions/2447475/best-practice-for-creating-objects-used-in-for-foreach-loops –

+1

Un error no relacionado es que la segunda versión se debe inicializar a nulo para evitar una asignación excesiva. –

Respuesta

12

Se podría tal vez ganar un poco de rendimiento, si escribir esto:

StringBuilder sb = new StringBuilder(); 
foreach(Type item in myCollection) 
{ 
    sb.Length = 0; 
} 

Así que hay que crear una instancia del StringBuilder sólo una vez y restablecer el tamaño en el bucle, lo que debería ser un poco más rápido que una instancia de un nuevo objeto .

+0

+1 punto bueno ... – SLaks

+1

+1: según el tamaño de la cadena construida y el búfer interno resultante en sb, esto podría hacer una diferencia medible. – Alex

+2

Podría, pero también podría no serlo. Cuando llamas a 'ToString', copia el buffer. Lo compararía, suponiendo que hubiera alguna razón para pensar que era sensible al rendimiento. –

14

No, no importará el rendimiento en donde lo declare.

Para la limpieza general del código, debe declararlo en el ámbito más interno que se utiliza, es decir. tu primer ejemplo.

+1

Esto debería compilar en la misma IL de todos modos, creo.Bueno, sería si no estuviera inicializando sb dos veces. –

+1

Corrígeme si estoy equivocado, pero si lo declaras dentro del ciclo, ¿no lo volverá inutilizable fuera de él (no declarado)? – NullUserException

+3

@NullUserException Sí, tienes razón. Pero si no lo necesita fuera del ciclo, es más claro declararlo dentro del ciclo – sloth

2

En el segundo ejemplo está creando una instancia adicional de StringBuilder. Aparte de eso, ambos son iguales, por lo que el problema de rendimiento es insignificante.

+0

Esto debería ser un comentario a la pregunta en mi opinión. – Shaihi

+0

@Shaihi - ¿Por qué? w69rdy está dando una respuesta a la pregunta. – mphair

1

No hay suficiente código aquí para indicar claramente una diferencia de rendimiento en su caso específico. Habiendo dicho eso, la diferencia entre declarar una variable de referencia dentro de un bucle como este vs. fuera es trivial para la mayoría de los casos.

1

La diferencia efectiva entre los dos ejemplos de código es que el segundo asignará 1 instancia más de StringBuilder que la primera. El impacto en el rendimiento de esto en comparación con el resto de su aplicación es esencialmente nada.

0

La mejor forma de comprobar es probando ambos métodos en un bucle, aproximadamente 100.000 cada uno. Mida la cantidad de tiempo que cada 100.000 iteraciones toma y compárelas. No creo que haya mucha diferencia. Pero hay una pequeña diferencia, sin embargo. El primer ejemplo tendrá tantas variables como el número de iteraciones. El segundo ejemplo solo tiene una variable. El compilador es lo suficientemente inteligente como para realizar algunas optimizaciones aquí, por lo que no notará una mejora en la velocidad. Sin embargo, si no desea utilizar el último objeto generado dentro del bucle una vez que está fuera del bucle nuevamente, entonces la primera solución sería mejor. En la segunda solución, solo toma un tiempo antes de que el recolector de basura libere el último objeto creado. En el primer ejemplo, el recolector de basura será un poco más rápido para liberar el objeto. Depende del resto del código, pero si almacena una gran cantidad de datos en este objeto StringBuilder, entonces el segundo ejemplo podría mantenerse en esta memoria mucho más tiempo, disminuyendo así el rendimiento de su código después de abandonar el ciclo!
Por otra parte, si los objetos consumen 100 KB y tiene 16 GB en su máquina, a nadie le importa ... El recolector de basura finalmente lo liberará nuevamente, probablemente tan pronto como salga del método que contiene este ciclo.

0

Si tiene otros segmentos de código de tipo similar, siempre puede crear perfiles o poner algunos temporizadores alrededor del código y ejecutar una prueba de tipo de referencia para verlo usted mismo. Otro factor sería la huella de memoria, que otros han comentado.

Cuestiones relacionadas