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