2012-08-16 24 views
6

Después de actualizar a DotNet 4.5, una consulta comenzó a darme OutOfMemoryExceptions.¿Por qué se lanzaría OutOfMemoryException mientras se usa PLINQ Take()?

El (destilada) consulta es:

var tests = new int[]{} 
    .AsParallel() 
    .GroupBy(_ => _) 
    .Take(int.MaxValue) 
    .ToArray(); 

les dejo esto para cualquier persona con el mismo problema. Voy a responder a continuación.

+2

¿Está ejecutando en 32 bits o 64 bits? – Oded

+0

proceso de 32 bits. –

+0

Estaba usando este tipo de código dentro de una función que recibió un parámetro con la cantidad de elementos que se devolverán. Pasar int.MaxValue (hubo una sobrecarga que hizo exactamente eso) esencialmente significaba 'tomar todo'. –

Respuesta

7

Parece ser un cambio en el marco.

El operador Take() se implementa en la clase interna TakeOrSkipQueryOperator. Hay una rama en el código que pasa por una función WrapHelper() que crea una instancia FixedMapHeap que a su vez crea una matriz de elementos clave del tamaño pasado originalmente a Take() (que sería una matriz de 8 GB en el ejemplo dado))

+0

Ok. Pero, ¿cómo arreglarlo? – Steven

+1

@Steven Establezca un valor 'Take 'para el que tenga suficiente memoria para almacenar tantos resultados. (O obtenga más memoria). – Servy

+3

Suena como una optimización razonable la mayor parte del tiempo; debería permitir una mejor paralelización en muchos casos, ya que diferentes hilos pueden escribir en diferentes partes de ese montón sin riesgo de interferir entre sí. El lado negativo en este caso es claro. –

Cuestiones relacionadas