2012-08-16 4 views
6

Nachdem ich auf DotNet 4.5 aktualisiert hatte, begann eine Abfrage mit OutOfMemoryExceptions.Warum sollte OutOfMemoryException ausgelöst werden, während PLINQ Take() verwendet wird?

Die (destilliert) Abfrage ist:

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

ich dies mit dem gleichen Problem für jedermann veröffentlichen. Ich antworte unten.

+2

Laufen Sie in 32-Bit oder 64-Bit? – Oded

+0

32-Bit-Prozess. –

+0

Ich habe diese Art von Code innerhalb einer Funktion verwendet, die einen Parameter mit der Anzahl der Elemente erhalten hat, die zurückgegeben werden sollen. Die Weitergabe von int.MaxValue (es gab eine Überlastung, die genau das tat) bedeutete im Wesentlichen "nimm alles". –

Antwort

7

Es scheint eine Änderung im Rahmen zu sein.

Der Operator Take() ist in der internen Klasse TakeOrSkipQueryOperator implementiert. Es gibt einen Zweig im Code, der eine WrapHelper() - Funktion durchläuft, die eine FixedMapHeap-Instanz erstellt, die wiederum ein Array von Key-Elementen mit der ursprünglich an Take() übergebenen Größe erstellt (was im angegebenen Beispiel ein Array von 8 GB wäre)).

+0

Ok. Aber wie kann ich es reparieren? – Steven

+1

@Steven Legen Sie einen 'Take'-Wert fest, für den Sie genügend Speicher haben, um so viele Ergebnisse zu speichern. (Oder mehr Speicher bekommen.) – Servy

+3

Klingt wie eine vernünftige Optimierung die meiste Zeit - sollte in vielen Fällen eine bessere Parallelisierung ermöglichen, da verschiedene Threads in verschiedene Teile dieses Heaps schreiben können, ohne sich gegenseitig zu stören. Die Down-Side ist in diesem Fall jedoch klar. –

Verwandte Themen