更新:以下错误似乎已经在PowerShell 5中得到解决。该错误仍然存在于3和4中。因此,除非您使用PowerShell 2或5,否则请勿使用管道处理任何巨大的文件。
考虑以下代码片段:
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
执行Get-DummyData | Out-Null
几次后,这将导致PowerShell的内存使用量不受控制地增长。我曾经看到过PowerShell的内存使用量一直增加到4 GB。
根据ANTS Memory Profiler,我们有许多东西坐在垃圾收集器的终结队列中。当我调用[GC]::Collect()
时,内存从4 GB降至仅70 MB。所以严格来说我们没有内存泄漏。
现在,当我完成一个长时间运行的管道操作后,我不能只能调用[GC]::Collect()
。我需要在管道操作期间进行垃圾回收。但是,如果我尝试在执行管道时调用[GC]::Collect()
...
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
...问题仍然存在。内存使用量再次不受控制地增长。我尝试了几种方法,例如添加[GC] :: WaitForPendingFinalizers()
,Start-Sleep -Seconds 10
等。我尝试更改垃圾回收器延迟模式并强制PowerShell使用服务器垃圾收集,但无济于事。我只是不能让垃圾回收器在管道执行时发挥作用。
在PowerShell 2.0中根本没有这个问题。有趣的是,$null = Get-DummyData
似乎也可以正常工作而没有内存问题。因此看起来与管道有关,而不是我们正在生成大量字符串的事实。
如何防止在长时间管道期间内存不受控制地增长?
旁注:
我的Get-DummyData函数仅供演示目的。我的真实问题是无法使用Get-Content
或Import-Csv
在PowerShell中读取大型文件。不,我没有将这些文件的内容存储在变量中。我严格使用管道,就像应该做的那样。 Get-Content .\super-huge-file.txt | Out-Null
也会产生相同的问题。
[System.GC] :: GetTotalMemory($true) | out-null
。 - Ross Patterson