在Windows PowerShell中,如何设置要使用的脚本的最大CPU%?

时间:2009-08-06 14:20:33

标签: powershell cpu

我希望将PowerShell进程使用的CPU时间百分比限制为一定数量 - 为了争论,让我们假设它是13%。

其他选项并非我所需要的: 1)设置优先级。 2)设置CPU亲和力。

基本上,我们有监控软件,如果总CPU使用率过高,则会抱怨。我们有一个日常流程可以解决这个问题 - 主要是无害的,但监控系统中的误报太多,当我们不希望这样做时,人们会被警告/错误所吸引。

该进程本身也让lsass.exe在运行时非常兴奋,并且还会发生其他进程。

我不知道PowerShell并且正在尝试修复其他人的Powershell。显然,在未来的某个时刻进行重写是很好的,但就目前而言,钟声响起并且令人烦恼。

6 个答案:

答案 0 :(得分:3)

你要求的是不可能的。 Windows内核负责调度CPU - 这是理所当然的。 (我一个人不想回到实模式DOS)。

您可以做的最好的事情是在脚本的每一行之间插入一个长Sleep()。但是无法保证任何特定的Powershell cmdlet / function / etc都会以您想要的方式限制自己。最终执行每个语句的脏工作的Windows API调用肯定不会。

具有讽刺意味的是,Raymond几天前就谈到了这个话题:http://blogs.msdn.com/oldnewthing/archive/2009/07/27/9849503.aspx

我真正的建议是修改你的脚本,看起来像:

try {
    Stop-CpuMonitor

    # ...the current script contents...
}
finally {
    Start-CpuMonitor
}                

答案 1 :(得分:1)

根据我的经验,没有办法规定CPU Powershell可以使用的百分比。我认为最好的做法是将Powershell的优先级设置为低,以允许其他任务/程序先行。我认为第一篇文章有​​一个很好的建议使用暂停(我是upvote,但我低于15个声望点这样做)这是你可能会看到的东西,但我认为它不会给你你正在寻找的控制。对不起,我的答案更多的是建议而非决议。

/亚光

答案 2 :(得分:1)

我真诚地怀疑有一种特别简单的方法来完成你的要求。如果CPU问题是一个大问题,我会结合几种策略,让调度程序负责其余的事情 - 它实际上非常适合管理负载。

使用ThreadPriority的建议有点问题,因为PowerShell会在新的Thread中生成每个新命令,您可以通过将所有内容封装在单行,cmdlet或某种函数上来解决这个问题。最好将整个PowerShell进程发送到空闲状态:

Get-Process -name powershell | foreach { $_.PriorityClass = "Idle" }

注意:这会将所有powershell实例发送到空闲状态,这可能不是所需的效果。当然也不能阻止脚本提升自己的优先级。

此外,如此处所述 - 使用sleep命令乱丢代码可以是确保其他进程有足够的CPU时间来处理其代码的有效方法。对于处理器而言,即使50-100ms也几乎是永恒的。

[System.Threading.Thread]::Sleep(50)

在这两种策略之间,你的脚本会在可用时运行,并且在出现时会慷慨地接受其他CPU需求。

答案 3 :(得分:0)

虽然我知道没有办法将任何进程的使用率按百分比实际限制到特定的CPU消耗量,但我想可能有人可能会改变PowerShell线程的优先级。所以我写了一个快速的脚本并进行了测试。

结果是,在“正常”和“最低”两者中,所花费的时间大致相同。看看CPU仪表小部件,CPU占用率约为27%,但我在四核盒上运行,所以这并不奇怪。在这两种情况下都采用了所有的CPU。我的机器当时没有做太多其他事情,所以那是另外2%,我想。

也许结果会因更繁忙的机器而异。

这是脚本:

function Spin
{
    param($iterations)

    for($i = 0; $i -lt $iterations; ++$i)
    {
        # Do nothing
    }
}

$thread = [System.Threading.Thread]::CurrentThread

Write-Host $thread.Priority
$start = [DateTime]::Now
Write-Host "[$start] Start"

Spin 10000000

$end = [DateTime]::Now
Write-Host "[$end] End"
$span = $end - $start
Write-Host "Time: $span"

$thread.Priority = "Lowest"
Write-Host $thread.Priority
$start = [DateTime]::Now
Write-Host "[$start] Start"

Spin 10000000

$end = [DateTime]::Now
Write-Host "[$end] End"
$span = $end - $start
Write-Host "Time: $span"

$thread.Priority = "Normal"

这是结果:

Normal
[08/06/2009 08:12:38] Start
[08/06/2009 08:12:55] End
Time: 00:00:16.7760000
Lowest
[08/06/2009 08:12:55] Start
[08/06/2009 08:13:11] End
Time: 00:00:16.8570000

另请注意,在Thread.Priority的文档中,它指出:

  

操作系统不需要遵守线程的优先级。

答案 4 :(得分:0)

在 C# 脚本文字上使用 AddType,它再次使用 P/Invoke 调用 Win32 函数 CreateJobObject、SetInformationJobObject(传递 JOBOBJECT_CPU_RATE_CONTROL_INFORMATION)和 AssignProcessToJobObject。用 C 编写一个包装程序来设置限制并在这样的工作中生成 PowerShell 脚本可能会更容易。

答案 5 :(得分:-1)

可能使用process lasso。当CPU使用率超过一定百分比时,除了我自己限制的进程的自动限制外,我只得到了积极的结果。

请注意,如果适合您,可以使用相当有限的免费版本进行测试。

PS:我不是为任何人工作。我现在只提供一个对我有用的程序。