2012-08-16 11 views
6

Dopo l'aggiornamento a DotNet 4.5, una query ha iniziato a darmi OutOfMemoryExceptions.Perché si dovrebbe generare OutOfMemoryException durante l'uso di PLINQ Take()?

L'(distillata) query è:

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

sto postando questo per chiunque con lo stesso problema. Risponderò di seguito.

+2

Sei in esecuzione in 32 bit o 64 bit? – Oded

+0

processo a 32 bit. –

+0

Stavo usando questo tipo di codice all'interno di una funzione che ha ricevuto un parametro con il numero di elementi da restituire. Passando a int.MaxValue (c'era un sovraccarico che faceva proprio questo) intendevo essenzialmente "prendere tutto". –

risposta

7

Sembra essere un cambiamento nel quadro.

L'operatore Take() è implementato nella classe interna TakeOrSkipQueryOperator. C'è un ramo nel codice che attraversa una funzione WrapHelper() che crea un'istanza FixedMapHeap che a sua volta crea una matrice di elementi chiave della dimensione passata in origine a Take() (che sarebbe un array di 8 Gb nell'esempio fornito).

+0

Ok. Ma come aggiustarlo? – Steven

+1

@Steven Impostare un valore 'Take' per il quale si dispone di memoria sufficiente per memorizzare tutti i risultati. (Oppure ottieni più memoria.) – Servy

+3

Suona come una ragionevole ottimizzazione per la maggior parte del tempo - dovrebbe consentire una migliore parallelizzazione in molti casi poiché i diversi thread possono scrivere in diverse parti di quell'heap senza il rischio di interferire l'uno con l'altro. Il downside in questo caso è chiaro però. –

Problemi correlati