UPDATE: Il seguente bug sembra essere risolto con PowerShell 5. Il bug rimane in 3 e 4. Quindi non elaborare nessun file enorme con la pipeline a meno che non si stia eseguendo PowerShell 2 o 5.Nessun garbage collection mentre la pipeline PowerShell è in esecuzione
si consideri il seguente frammento di codice:
function Get-DummyData() {
for ($i = 0; $i -lt 10000000; $i++) {
"This is freaking huge!! I'm a ninja! More words, yay!"
}
}
Get-DummyData | Out-Null
Questo causerà PowerShell utilizzo della memoria a crescere in maniera incontrollata. Dopo aver eseguito Get-DummyData | Out-Null
un paio di volte, ho visto l'utilizzo della memoria di PowerShell arrivare fino a 4 GB.
In base allo ANTS Memory Profiler, abbiamo un sacco di cose da fare nella coda di finalizzazione del garbage collector. Quando chiamo [GC]::Collect()
, la memoria passa da 4 GB a soli 70 MB. Quindi non abbiamo una perdita di memoria, in senso stretto.
Ora, non è abbastanza buono per me essere in grado di chiamare [GC]::Collect()
quando ho finito con un'operazione di pipeline di lunga durata. Ho bisogno di garbage collection per accadere durante il un'operazione di pipeline. Tuttavia, se provo a richiamare [GC]::Collect()
mentre il gasdotto è in esecuzione ...
function Get-DummyData() {
for ($i = 0; $i -lt 10000000; $i++) {
"This is freaking huge!! I'm a ninja! More words, yay!"
if ($i % 1000000 -eq 0) {
Write-Host "Prompting a garbage collection..."
[GC]::Collect()
}
}
}
Get-DummyData | Out-Null
... il problema rimane. L'utilizzo della memoria cresce di nuovo in modo incontrollabile. Ho provato diverse varianti di questo, come ad esempio l'aggiunta di [GC]::WaitForPendingFinalizers()
, Start-Sleep -Seconds 10
, ecc. Ho provato a cambiare il garbage collector latency modes e forzando PowerShell a utilizzare server garbage collection senza alcun risultato. Non riesco proprio a far sì che il garbage collector faccia la sua parte mentre la pipeline è in esecuzione.
Questo non è affatto un problema in PowerShell 2.0. È anche interessante notare che anche $null = Get-DummyData
sembra funzionare senza problemi di memoria. Quindi sembra legato alla pipeline, piuttosto che il fatto che stiamo generando tonnellate di stringhe.
Come è possibile evitare che la memoria si sviluppi in modo incontrollato durante le lunghe condotte?
Nota a margine:
mio Get-DummyData funzione è solo a scopo dimostrativo. Il mio problema reale è che non riesco a leggere file di grandi dimensioni in PowerShell usando Get-Content
o Import-Csv
. No, sono non memorizzando il contenuto di questi file in variabili. Sono strictly using the pipeline come dovrei. Get-Content .\super-huge-file.txt | Out-Null
produce lo stesso problema.
Sembra un po 'come http://stackoverflow.com/q/30918020/258523. –
La parte di esaurimento della memoria sembra un bug. È possibile ridurre in modo significativo il tempo della CPU evitando piping/enumerando 10 milioni di oggetti utilizzando assunzioni, casting o enumerazione delle proprietà –
Non riesco a riprodurre il problema con lo snippet di codice fornito. –