【问题标题】:How is the new PowerShell 7 ForEach-Object Parallel implemented?新的 PowerShell 7 ForEach-Object Parallel 是如何实现的?
【发布时间】:2020-03-24 19:13:43
【问题描述】:

PowerShell 7 引入了一项非常需要的功能,用于并行运行管道输入。

PowerShell 7 的文档没有提供有关如何实现的任何详细信息。

在使用过 PoshRSJobInvoke-Parallel 模块之前,我知道运行空间传统上被认为是在 powershell 中进行并行操作比运行 PowerShell 作业更有效的方法。我已经阅读了一些混合内容,表明这是现在使用线程而不是运行空间,但找不到其他具体内容。

我非常感谢您对以下方面的技术见解:

  1. 从 .NET 角度来看,执行的生命周期是什么
  2. 新功能是运行空间还是线程? (或者运行空间只是 System.Management.Automation 中的一个 .NET 线程?)
  3. 既然我们正在转向并行操作,这是否会给传统调试带来任何复杂性? 从历史上看,我对运行空间进行了一段艰难的调试,并且不确定哪些选项可能会得到改进

【问题讨论】:

  • 根据我看到的文章,它使用运行空间。您需要将 $vars 发送到其中 [通常使用 $Using:]。它将所有需要的模块和功能以及诸如此类的东西加载到每个运行空间中,因此设置和拆除需要时间。到目前为止,我还没有看到任何有关调试的信息。
  • 独立的运行空间,通过新的内部 API (PSTaskPool) 进行管理。 The RFC 详细介绍了关于实现和约束的一些 细节。 The source code 还包含许多有用的 cmets
  • 以防万一(谁知道)还有 SplitPipeline 具有一些独特的功能(恕我直言,确实如此),例如它适用于非常大或无限的输入。
  • 还有start-threadjob,我相信是同一个人写的。它不会序列化像 start-job 这样的对象。
  • RFC 也向我指出了一些很棒的信息。如果稍后回答其中一些问题,将在此处查看并发布答案。 RFC0044-ForEach-Parallel-Cmdlet

标签: powershell runspace powershell-core


【解决方案1】:

调试 foreach-object -parallel:

我需要第二个 pwsh 进程来执行此操作。在第一个做:

foreach-object -parallel { Wait-Debugger;1;2;3 }

然后在第二个窗口中,找出另一个 pwsh 的 pid 是什么。然后进入那个pshost进程。查看运行空间,并调试可用性为“InBreakpoint”的运行空间。 “v”的意思是“越过”。

get-process pwsh

 NPM(K)    PM(M)      WS(M)     CPU(s)      Id  SI ProcessName
 ------    -----      -----     ------      --  -- -----------
     64    44.32      82.23       1.70    3912  12 pwsh
     63    40.66      78.03       1.36    6472  12 pwsh

$pid
6472

Enter-PSHostProcess 3912

get-runspace

 Id Name            ComputerName    Type          State         Availability
 -- ----            ------------    ----          -----         ------------
  1 Runspace1       localhost       Local         Opened        Busy
  2 PSTask:1        localhost       Local         Opened        InBreakpoint
  3 RemoteHost      localhost       Local         Opened        Busy

debug-runspace 2
v
v
v

如果你运行 foreach-object -parallel -asjob,你可以在同一个窗口中使用 get-runspace 和 debug-runspace。但是步进时看不到输出。

foreach-object -parallel { Wait-Debugger;1;2;3 } -asjob
get-runspace

 Id Name            ComputerName    Type          State         Availability
 -- ----            ------------    ----          -----         ------------
  1 Runspace1       localhost       Local         Opened        Available
  2 PSTask:1        localhost       Local         Opened        InBreakpoint

debug-runspace 2
v
v
v

这是一个新的调试视频,其中包含一些使用 Vscode 的高级设置:https://www.reddit.com/r/PowerShell/comments/gn0270/advanced_powershell_debugging_techniques/

【讨论】:

    【解决方案2】:

    发现 Paul Higinbotham 撰写的这篇精彩的博文 PowerShell ForEach-Object Parallel Feature

    从这篇博文中,我摘录了主要亮点:

    脚本块在称为 PowerShell 运行空间的上下文中运行。运行空间上下文包含所有已定义的变量、函数和加载的模块。

    如前所述,新的 ForEach-Object -Parallel 功能使用现有的 PowerShell 功能来并发运行脚本块....PowerShell 本身根据其设计和历史对脚本如何并发运行施加了条件。脚本必须在运行空间上下文中运行,并且在运行空间中一次只能运行一个脚本线程。因此,为了同时运行多个脚本,必须创建多个运行空间。

    因此,它确认运行空间是这方面的主要驱动力,并提供了有关线程安全操作等的更多信息。之前提供的有关运行空间的任何答案或详细信息都与此处相关,因为这是官方标准库中用于并行操作的运行空间的成熟实现。社区已经完成了面向运行空间的其他实现,但现在包含在没有外部模块依赖项的情况下。

    感谢Paul 为社区做出如此出色的贡献! ?

    【讨论】:

    • 我不认为你可以。运行空间是线程化的,因此不确定您是否可以使用调试器分成单独的运行空间。我从来没有成功尝试过,所以如果你发现其他情况,请告诉我。听起来可能是一个很好的单独问题
    • 有一个调试运行空间命令。但是你可能不得不从另一个进程中中断,除非循环以某种方式在后台运行。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-14
    • 2019-07-25
    • 1970-01-01
    • 2020-05-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多