【问题标题】:Memory usage powershell 7.03 Foreach-object Parallel内存使用powershell 7.03 Foreach-object Parallel
【发布时间】:2020-08-26 11:40:02
【问题描述】:

我正在尝试对合理的数据集进行处理,并尝试在 powershell 7.x 中使用 Foreach-Object -Parallel。

每次运行时,我都会发现内存不足。似乎每 1000 个对象大约 1 gig,我现在已将其提炼为以下代码。 (这个剂量除了创建然后销毁4000次运行之外什么都不做)

$a = new-object object[] 4000
$a | ForEach-Object -ThrottleLimit 40 -Parallel {
  #Code to do something in here.
}

如果您将 $a 的值更改为 1000,则将消耗大约 1 gig 的内存,将 $a 设置为 2000 然后 2 gig 的内存等。油门限制不会改变消耗的内存量只是数字CPU 线程数。

当您要处理脚本块的次数变大时,这会导致问题。在我的示例中,我需要使用脚本块中的代码处理 20,000 台计算机。运行该代码时,脚本消耗 16+ gig 并导致分页。

任何人都可以确认他们是否遇到相同的问题或是否有已知的解决方法。

【问题讨论】:

  • 是的,这种行为在 7.0.3 中仍然存在。问题似乎与垃圾收集器调度有关,在管道正确返回后运行[gc]::Collect() 会释放所有底层内存。作为一种解决方法,您可能希望将输入分块成具有可接受的内存压力水平的批次,例如一次 1000 台计算机 - 然后在开始下一批之前手动调用 [gc]::Collect()
  • 谢谢 我不记得启动垃圾收集器的命令了。我想是时候为 PowerShell 团队发布一个 github 问题了。
  • 在 4 核或 8 核计算机上使用 40 个线程真的有好处吗?
  • 进程往往受网络限制,CPU 线程往往不会做太多事情。 IT 只是一个例子。如果您使用一个线程运行上述代码,您将获得相同的结果。改变线程的数量,它不会改变垃圾收集器跟不上的结果。

标签: powershell powershell-7.0


【解决方案1】:

感谢 Mathias R. Jessen,他确认这仍然是一个问题和一个建议。将流程分解为现在只处理有限数量的机器以限制内存使用。


$ObjectsToProcess = (1..4102)
$Batch = 0
$BatchSize = 100
do {
    # Create an arrary with limited number of objects in it for memory management
    $ObjectsProcessing = [System.Collections.Generic.List[string]]::new()
    for ($i = $Batch; (($i -lt $Batch + $BatchSize) -and ($i -lt $ObjectsToProcess.count)); $i++) {
        $ObjectsProcessing.add($ObjectsToProcess[$i])
    }

    $ObjectsProcessing | ForEach-Object -ThrottleLimit 40 -Parallel {
        $_
        # Main script in this block now.
    }
    [gc]::Collect() # garbage collection to recover memory
    
    $Batch = $Batch + $BatchSize
} while ($Batch -lt $ObjectsToProcess.count)

这将允许一次处理多达 $BatchSize 的机器,同时处理的机器数量由 ThrottleLimit 控制。内存消耗可以通过 $BatchSize 来控制。

现在处理 4102 个对象的内存现在从未超过 200 Meg 与之前的 4 Gig。

【讨论】:

    猜你喜欢
    • 2022-10-14
    • 1970-01-01
    • 2019-07-25
    • 1970-01-01
    • 1970-01-01
    • 2021-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多