2009-11-02 35 views
5

List1 en el siguiente ejemplo es SortedList (Of MyClass) y contiene 251 miembros.Ciclismo a través de SortedList: ¿por qué es más rápido?

Los primeros dos bloques de código se ejecutan en 15.5 segundos.

For cnt As Integer = 1 To 1000000 
     For Each TempDE In List1 
      Dim F As String = TempDE.Key 
      TempDE.Value.x1 = 444 
     Next 
    Next 

 

For cnt As Integer = 1 To 1000000 
     For Each TempDE As KeyValuePair(Of String, phatob) In List2 
      Dim F As String = TempDE.Key 
      TempDE.Value.x1 = 444 
     Next 
    Next 

Esta uno ejecuta en 5,6 segundos.

For cnt As Integer = 0 To 999999 
     For cnt2 As Integer = 0 To 250 
      Dim F As String = List1.Keys(cnt2) 
      List1.Values(cnt2).x1 = 444 
     Next 

    Next 

¿Por qué los dos primeros bloques de código de manera mucho más lenta?

+0

No estoy seguro, pero quizás el bucle For Each tenga una sobrecarga mayor que el bucle For sobre los enteros. Por lo tanto, la segunda línea podría ser responsable de la aceleración? Realmente no lo sé –

+0

¿Los primeros dos bucles toman 15.5 segundos JUNTOS, o CADA UNO? – Artelius

+0

@Artelius - Cada –

Respuesta

4

SortedList amplía una colección implementando IComparer para proporcionar la funcionalidad de clasificación. Internamente, implementa 2 matrices para almacenar los elementos de la lista: una matriz para la clave y otra para los valores. .NET Array está optimizado para un rápido acceso en orden y rápido al azar.

Mi sospecha de por qué los primeros 2 son lentos se debe a que la declaración foreach en una SortedList es un envoltorio alrededor del Enumerador. Calling foreach consultará el enumerador, llamará a MoveNext y Current. Además, aunque la lista genérica puede involucrar el boxeo y el desempaquetado a medida que recorre la lista, y puede generar una sobrecarga de rendimiento que normalmente no obtendría accediendo por Index.

+0

Esta es una mejor versión de lo que estaba tratando de obtener con mi respuesta :) – Zwergner

3

Traté de buscar documentación sobre exactamente cómo se comporta For Each, pero no pude encontrarlo.

Mi teoría es que el uso de las instrucciones For Each copia el objeto en la lista a otro lugar en la memoria y luego lo copia de nuevo en la lista cuando termina cada iteración del ciclo.

Otra posibilidad es que llama al constructor al comienzo de cada iteración y luego deconstruye y llama al constructor nuevamente para reiniciarlo para la siguiente iteración.

No estoy seguro de ninguna de estas teorías, pero la mayor diferencia entre 3 y (1 o 2) es la falta de For Each.

EDIT: Encontrará documentación al MSDN.

He aquí un extracto:

Cuando se inicia la ejecución del bucle For Each ... A continuación, Visual Basic comprueba que grupo se refiere a un objeto de colección válido. Si no, arroja una excepción. De lo contrario, llama al método MoveNext y a la propiedad Current del objeto enumerador para devolver el primer elemento. Si MoveNext indica que no hay un elemento siguiente, es decir, si la colección está vacía, el bucle For Each finaliza y el control pasa a la instrucción que sigue a la instrucción Next. De lo contrario, Visual Basic establece elemento en el primer elemento y ejecuta el bloque de instrucción.

Así que en general suena como For Each es más "administrado" y hace un montón de gastos generales para asegurarse de que todo coincide. Como resultado, es más lento.

3

Creo que el compilador puede optimizar mejor el bloque 3 debido al rango de bucle fijo. En los bloques uno y 2, el compilador no sabrá cuál es el límite superior del bucle hasta que evalúe la Lista, lo que la hace más lenta.

+0

Definitivamente un punto válido. Creo que contribuye, pero tal vez no todo el problema. – Zwergner

2

Mi conjetura aleatoria: La Lista1 contiene ~ 750 elementos (y no solo 250). Su tercer caso es más rápido, porque no itera sobre cada elemento que tiene List1.

+0

Ahora me estoy inclinando por esto como la respuesta correcta, ya que mis propias pruebas muestran 'For Each' siendo aproximadamente la misma velocidad que la iteración regular. Para respaldar aún más esta afirmación, está iterando más de 251 elementos (0 a 250) sin error, por lo que la lista no contiene la cantidad de elementos que cree que contiene. – Zwergner

Cuestiones relacionadas