powershell - PowerShell 管道正在执行时没有垃圾收集

标签 powershell memory garbage-collection powershell-3.0

更新: 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

这将导致 PowerShell 内存使用量无法控制地增长。执行 Get-DummyData | 后Out-Null 几次,我看到 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 等。我尝试更改垃圾收集器 latency modes并强制 PowerShell 使用 server garbage collection 无济于事。我只是无法让垃圾收集器在管道执行时完成它的工作。

这在 PowerShell 2.0 中根本不是问题。值得注意的是,$null = Get-DummyData 似乎也可以在没有内存问题的情况下工作。所以它似乎与管道有关,而不是我们生成大量字符串这一事实。

如何防止我的内存在长管道期间不受控制地增长?

旁注:

我的 Get-DummyData 函数仅用于演示目的。我的实际问题是我无法使用 Get-ContentImport-Csv 在 PowerShell 中读取大文件。不,我将这些文件的内容存储在变量中。我应该是 strictly using the pipeline获取内容 .\super-huge-file.txt | Out-Null 产生同样的问题。

最佳答案

这里有几点需要指出。首先,GC 调用确实在管道中工作。这是一个只调用 GC 的管道脚本:

1..10 | Foreach {[System.GC]::Collect()}

这是脚本运行期间 GC 的性能图:

enter image description here

但是,仅仅因为您调用了 GC,并不意味着私有(private)内存使用量将恢复到您在脚本启动之前的值。 GC 收集只会收集不再使用的内存。如果有对对象的根引用,则它没有资格被收集(释放)。因此,虽然 GC 系统通常不会在 C/C++ 意义上泄漏,但它们可能拥有比它们应有的更长的时间持有对象的内存囤积。

在使用内存分析器查看这一点时,似乎大部分多余的内存都被带有参数绑定(bind)信息的字符串副本占用了:

enter image description here

这些字符串的根如下所示:

enter image description here

我想知道是否有一些日志记录功能导致 PowerShell 卡在字符串化的表单管道绑定(bind)对象上?

顺便说一句,在这种特定情况下,分配给 $null 以忽略输出的内存效率要高得多:

$null = GetDummyData

此外,如果您需要简单地编辑文件,请查看 PowerShell Community Extensions 中的 Edit-File 命令。 3.2.0。只要您不使用 SingleString 开关参数,它就应该是内存高效的。

关于powershell - PowerShell 管道正在执行时没有垃圾收集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31620763/

相关文章:

powershell - 从字节转换为GB或MB不会返回任何内容

c++ - 在 C++ 中使用指针 vector 时会泄漏内存吗?

java - 为什么 G1 提供更好的暂停时间但吞吐量较低?

java - 如何在应用程序中持续保持 5GB 内存,而不会因 GC 而导致性能不佳?

java - Graal 不支持垃圾收集器

sql-server - 如何比较 Invoke-Sqlcmd 的结果?

powershell - 简化基于 Powershell 的文件编辑

powershell - Powershell附加CSV错误

javascript - 一旦内存达到 4GB 标记,如何防止 Microsoft Edge 重新加载我的页面?

memory - Neo4j 删除内存不足的图