4

throttlelimit参数foreach -parallel可以控制执行脚本时使用多少进程。但即使我设置throttlelimit大于 5,我也不能有超过 5 个进程。

该脚本在多个 powershell 进程中执行。所以我检查了脚本中的 PID。然后对 PID 进行分组,这样我就可以知道有多少进程用于执行脚本。

function GetPID() {
    $PID
}

workflow TestWorkflow {
    param($throttlelimit)
    foreach -parallel -throttlelimit $throttlelimit ($i in 1..100) {
        GetPID
    }
}

foreach ($i in 1..8) {
    $pids = TestWorkflow -throttlelimit $i
    $measure = $pids | group | Measure-Object
    $measure.Count
}

输出是

1
2
3
4
5
5
5
5

对于$i小于或等于 5,我有$i进程。但是对于$i大于 5,我只有 5 个进程。执行脚本时有什么方法可以增加进程数吗?

编辑:为了回应@SomeShinyObject 的回答,我添加了另一个测试用例。这是对@SomeShinyObject 给出的示例的修改。我添加了一个函数S,它只做 10 秒的睡眠。

function S($n) {
    $s = Get-Date
    $s.ToString("HH:mm:ss.ffff") + " start sleep " + $n
    sleep 10
    $e = Get-Date
    $e.ToString("HH:mm:ss.ffff") + " end sleep " + $n + " diff " + (($e-$s).TotalMilliseconds)
}

Workflow Throttle-Me {
    [cmdletbinding()]
    param (
        [int]$ThrottleLimit = 10,
        [int]$CollectionLimit = 10
    )

    foreach -parallel -throttlelimit $ThrottleLimit ($n in 1..$CollectionLimit){
        $s = Get-Date
        $s.ToString("HH:mm:ss.ffff") + " start " + $n
        S $n
        $e = Get-Date
        $e.ToString("HH:mm:ss.ffff") + " end " + $n + " diff " + (($e-$s).TotalMilliseconds)
    }
}

Throttle-Me -ThrottleLimit 10 -CollectionLimit 20

这是输出。我按时间(秒数)对输出进行分组,并在每个组中重新排序以使其更清晰。很明显,函数S是 5 乘 5 调用的,尽管我设置throttlelimit为 10(首先我们有start sleep 6..10,10 秒后,我们有start sleep 1..5,10 秒后start sleep 11..15,10 秒后start sleep 16..20)。

03:40:29.7147 start 10
03:40:29.7304 start 9
03:40:29.7304 start 8
03:40:29.7459 start 7
03:40:29.7459 start 6
03:40:29.7616 start 5
03:40:29.7772 start 4
03:40:29.7772 start 3
03:40:29.7928 start 2
03:40:29.7928 start 1

03:40:35.3067 start sleep 7
03:40:35.3067 start sleep 8
03:40:35.3067 start sleep 9
03:40:35.3692 start sleep 10
03:40:35.4629 start sleep 6

03:40:45.3292 end sleep 7 diff 10022.5353
03:40:45.3292 end sleep 8 diff 10022.5353
03:40:45.3292 end sleep 9 diff 10022.5353
03:40:45.3761 end sleep 10 diff 10006.8765
03:40:45.4855 end sleep 6 diff 10022.5243
03:40:45.3605 end 9 diff 15630.1005
03:40:45.3917 end 7 diff 15645.7465
03:40:45.3917 end 8 diff 15661.3313
03:40:45.4229 end 10 diff 15708.2274
03:40:45.5323 end 6 diff 15786.3969
03:40:45.4386 start sleep 5
03:40:45.4542 start sleep 4
03:40:45.4542 start sleep 3
03:40:45.4698 start sleep 2
03:40:45.5636 start sleep 1
03:40:45.4698 start 11
03:40:45.4855 start 12
03:40:45.5011 start 13
03:40:45.5167 start 14
03:40:45.6105 start 15

03:40:55.4596 end sleep 3 diff 10005.4374
03:40:55.4596 end sleep 4 diff 10005.4374
03:40:55.4596 end sleep 5 diff 10021.0426
03:40:55.4752 end sleep 2 diff 10005.3992
03:40:55.5690 end sleep 1 diff 10005.3784
03:40:55.4752 end 3 diff 25698.0221
03:40:55.4909 end 5 diff 25729.302
03:40:55.5065 end 4 diff 25729.2523
03:40:55.5221 end 2 diff 25729.2559
03:40:55.6159 end 1 diff 25823.032
03:40:55.5534 start sleep 11
03:40:55.5534 start sleep 12
03:40:55.5690 start sleep 13
03:40:55.5846 start sleep 14
03:40:55.6784 start sleep 15
03:40:55.6002 start 16
03:40:55.6002 start 17
03:40:55.6159 start 18
03:40:55.6326 start 19
03:40:55.7096 start 20

03:41:05.5692 end sleep 11 diff 10015.8226
03:41:05.5692 end sleep 12 diff 10015.8226
03:41:05.5848 end sleep 13 diff 10015.8108
03:41:05.6004 end sleep 14 diff 10015.8128
03:41:05.6942 end sleep 15 diff 10015.8205
03:41:05.5848 end 12 diff 20099.3218
03:41:05.6004 end 11 diff 20130.5719
03:41:05.6161 end 13 diff 20114.9729
03:41:05.6473 end 14 diff 20130.5962
03:41:05.6942 end 15 diff 20083.7506
03:41:05.6317 start sleep 17
03:41:05.6317 start sleep 16
03:41:05.6473 start sleep 18
03:41:05.6629 start sleep 19
03:41:05.7411 start sleep 20

03:41:15.6320 end sleep 16 diff 10000.3608
03:41:15.6320 end sleep 17 diff 10000.3608
03:41:15.6477 end sleep 18 diff 10000.3727
03:41:15.6633 end sleep 19 diff 10000.3709
03:41:15.7414 end sleep 20 diff 10000.3546
03:41:15.6477 end 16 diff 20047.4375
03:41:15.6477 end 17 diff 20047.4375
03:41:15.6633 end 18 diff 20047.4295
03:41:15.7101 end 19 diff 20077.5169
03:41:15.7414 end 20 diff 20031.7909
4

2 回答 2

2

我相信你的测试有点缺陷。根据这篇TechNet 文章$PID不是脚本工作流中的可用变量。

可以在此站点上找到带有解释的更好测试

基本上,ThrottleLimit设置为理论上的[Int32]::MaxValue. 海报设计了一个更好的测试来检查并行处理(稍作修改):

Workflow Throttle-Me {
    [cmdletbinding()]
    param (
        [int]$ThrottleLimit = 10,
        [int]$CollectionLimit = 10
    )

    foreach -parallel -throttlelimit $ThrottleLimit ($n in 1..$CollectionLimit){
        "Working on $n"
        "{0:hh}:{0:mm}:{0:ss}" -f (Get-Date)
    }
}
于 2017-04-27T02:27:48.093 回答
0

我不能代表那个特定的 cmdlet ,但正如您发现的那样,PowerShell 每个 PID 只使用一个线程。解决这个问题的常用方法是PSJobsRunspaces。运行空间比 PSJobs 更难,但它们的性能也明显更好,这使它们成为流行的选择。缺点是您的整个代码必须围绕它们进行解析,这意味着在大多数情况下需要完全重写。

不幸的是,尽管微软大力推动 PowerShell,但它并不是为性能和速度而设计的。但它在绑定到 .NET 时表现得尽可能好

于 2017-04-27T01:34:12.077 回答