Un amigo y yo estábamos un poco perplejos durante una discusión de programación de hoy. Como ejemplo, creamos un problema ficticio de tener un List<int>
de n enteros aleatorios (típicamente 1.000.000) y queríamos crear una función que devolviera el conjunto de todos los enteros que había más de uno. Bastante sencillo. Creamos una instrucción LINQ para resolver este problema y un algoritmo simple de ordenación por inserción.¿Por qué las operaciones LINQ pueden ser más rápidas que un bucle normal?
Ahora, cuando probamos la velocidad con la que se ejecutó el código (usando System.Diagnostics.StopWatch
), los resultados fueron confusos. El código LINQ no solo superó al tipo simple, sino que ejecutó más rápido que un soloforeach
/for
que solo hizo un solo bucle de la lista, y que no tenía operaciones dentro (que, en una pista lateral, pensé que el compilador debía descubrir y eliminar todo junto).
Si generamos un nuevo List<int>
de números aleatorios en la misma ejecución del programa y ejecutamos nuevamente el código LINQ, el rendimiento aumentaría en órdenes de magnitud (típicamente mil veces). El rendimiento de los bucles vacíos fue, por supuesto, el mismo.
Entonces, ¿qué está pasando aquí? ¿LINQ utiliza el paralelismo para superar los bucles normales? ¿Cómo son estos resultados aún posibles? LINQ usa quicksort que se ejecuta en n * log (n), que por definición ya es más lento que n.
¿Y qué ocurre en el salto de rendimiento en la segunda pasada?
Estábamos desconcertados e intrigados con estos resultados y esperábamos que la comunidad aclarara algunas ideas, solo para satisfacer nuestra propia curiosidad.
Por favor, publique un código. –
¿Quizás podría compartir su prueba? –
Publica tu código. Probablemente no esté considerando la [ejecución diferida] (http://blogs.msdn.com/b/charlie/archive/2007/12/09/deferred-execution.aspx). –