有没有办法让powershell脚本在纳秒内休眠?

有没有办法让powershell脚本在纳秒内休眠?,powershell,Powershell,我正在使用以下PowerShell脚本生成事件并模拟不同的系统负载。当$sleepIntervalInMilliSeconds=0时,CPU使用率为100% 如果$sleepIntervalInMilliSeconds>=1,则CPU使用率相似(56%) 我认为脚本需要以纳秒级而不是毫秒级休眠,这样我就可以将CPU负载控制在70%、80%和90% 有办法做到这一点吗?浮点数

我正在使用以下PowerShell脚本生成事件并模拟不同的系统负载。当
$sleepIntervalInMilliSeconds=0
时,CPU使用率为100%

如果
$sleepIntervalInMilliSeconds>=1
,则CPU使用率相似(56%)

我认为脚本需要以纳秒级而不是毫秒级休眠,这样我就可以将CPU负载控制在70%、80%和90%

有办法做到这一点吗?浮点数<1似乎不起作用。谢谢你提供任何线索

Param(
  [int]$sleepIntervalInMilliSeconds = 0
)

$eventGenScript = {
  $logName = "TestLog"
  $sourceName = "TestSource"

  while($true) {
    Write-EventLog -LogName $logName -Source $sourceName -Message "perfLog" -EventId 0 -EntryType information
    Start-Sleep -Milliseconds $using:sleepIntervalInMilliSeconds
  }
}

$threadCount = 2

for($i=0; $i -lt $threadCount; $i++)
{
  Start-Job $eventGenScript  
}

read-host "type a key to exit."

我不认为自己是OS调度专家,但一般来说应该是这样的:

具有抢占式多任务模型的操作系统通过为进程(线程)提供可用于执行的时间片(或数量)来工作。然后,进程可以选择消耗所有分配的时间(导致100%的CPU消耗),或者只消耗部分时间片并将剩余时间返回操作系统(通过调用某种
sleep
函数)。当时间片完全消耗时,操作系统将控制并将其传递给另一个线程,这样它也有机会运行。这个过程一直持续到你关掉电脑。这就是所谓的“日程安排”。多核CPU使事情变得有点复杂,因为在任何时候都可能有多个时间片可用。由于单线程在任何时候都不能消耗超过1个时间片,因此单线程进程不能在多核CPU上产生100%的负载(除非运行其中的几个)。时间片大小通常具有固定大小,不能太短(它会导致在线程之间切换浪费大量CPU)或太长(因为进程的响应性会降低)。若并没有任何东西可以运行,那个么时间片将分配给将CPU切换到低功耗状态的特殊系统进程(Windows中的系统空闲进程)

Start Sleep
cmdlet本质上就是我上面提到的
Sleep
调用,它对操作系统说:“我放弃参与
n
毫秒的调度”,这意味着您的进程只能在时间片的粒度上选择睡眠周期。基本上,您唯一的选择就是要跳过多少时间片(同样,也不能保证过程会在这么长时间后被唤醒)

因为您不能用所需的粒度控制睡眠时间,所以您可以尝试控制时间片中消耗的时间量。首先,让我们忘记
编写事件日志
,因为它会用无用的消息淹没事件日志,并做一些更简单的事情

while ($true) {}
无主体的无休止循环完美地消耗了我的4核CPU的1个内核,产生了25%的CPU负载(其他3个内核处于空闲状态)。我们可以将其设置为脚本块,并在后台运行几次:

$el = { while ($true) {} };
$numCores = (Get-WmiObject -Class Win32_ComputerSystem).NumberOfLogicalProcessors;
$jobs = 1..$numCores | ForEach-Object { Start-Job -ScriptBlock $el };
Start-Sleep -Seconds 30
$jobs | Remove-Job -Force
我们启动无休止循环的后台作业,每个核心一个作业,睡眠30秒,然后杀死它们。我们可以在具有任意数量内核的系统上产生100%的CPU负载。现在是时候让它消耗更少的CPU了。为此,我们将在无限循环中运行有限循环,然后再睡一会儿。现在,应该仔细选择有限循环的长度,并且将是非常特定于系统的

$loopIterations = 24000;

$el = 
{
    while ($true) 
    {
        for ($i = 0; $i -lt $args[0]; ++$i){}
        Start-Sleep -Milliseconds 1
    } 
};
$numCores = (Get-WmiObject -Class Win32_ComputerSystem).NumberOfLogicalProcessors;
$jobs = 1..$numCores | ForEach-Object { Start-Job -ScriptBlock $el -ArgumentList $loopIterations};
Start-Sleep -Seconds 30
$jobs | Remove-Job -Force

此代码在我的系统上消耗90%的CPU。您必须对其进行调整,以便将CPU加载到您想要的水平。

如果我没有弄错的话,系统大小是16毫秒。指定1或2毫秒的睡眠时间(或10毫秒)与指定纳秒间隔没有任何区别。此外,您确定要通过写入事件日志来加载CPU吗?应该有更好的方法。@n0rd,您应该将这两条评论汇总为一个答案。