【问题标题】:Get Average CPU utilization for test execution in powershell在 powershell 中获取测试执行的平均 CPU 利用率
【发布时间】:2014-05-12 16:10:57
【问题描述】:

背景:
我想运行一个测试,并在它运行时收集 CPU 利用率。基本上,当我开始测试时,我还想开始收集 CPU 利用率数据,在测试结束时,我还想停止收集 CPU 利用率数据(然后取平均值)。
在 Win7 上使用 PowerShell 3

方法:
在测试开始时,我添加了一个启动后台作业的函数。后台作业执行一个脚本块,该脚本块运行一个“while ($true)”循环,该循环收集平均 CPU 利用率并将其保存到文件中。在测试结束时,我读取文件,平均收集的数据并停止并删除作业。

问题:
对于当前的方法,脚本块并不总是被执行,也不会收集新数据。如果我多次运行测试,脚本块会被执行(在其中一次运行中)——我想不出任何相关的东西或这种行为。如果我在测试中的任何地方使用断点,脚本块也总是会被执行。
想不出别的办法。

需要的答案:
1. 为什么脚本块没有被执行?以及如何让它执行?
2. 是否有其他方法可以在测试期间收集资源数据?

请注意,代码已通过各种尝试和失败运行,不再“漂亮”。
代码:

function Start-ResourceMonitor
{
    param()
    $avg=@()
    $timestamp = Get-Date -Format o | foreach {$_ -replace ":", "."}
    $compName=$env:COMPUTERNAME
    $myFilePath = Join-Path -path $env:TEMP -childpath .\temp_$timestamp.txt
    $scriptBlock = {
        $avgSB = $args[0]
        $timestampSB = $args[1]
        while ($true) {
            $avgSB += Get-WmiObject win32_processor -computername $args[2] | Measure-Object -property LoadPercentage -Average | Foreach {$_.Average}            
            $avgSB | Out-File -FilePath $args[3] -Force
            start-sleep -Milliseconds 500 
        }
    }
    $res = start-job -RunAs32 -Name 'MyJob' -ScriptBlock $scriptBlock -ArgumentList @($avg,$timestamp,$compName,$myFilePath)
    while (($res.State -ne 'Running') -or (-not (Test-Path $myFilePath))){
        start-sleep -Milliseconds 500
    }
}

[other test functions]

function Stop-ResourceMonitor
{
    param()
    Stop-Job -Name MyJob
    $testFN = Get-ChildItem -Path $env:TEMP -Filter "temp*.txt" | sort LastWriteTime -Descending | select -First 1
    $global:CPU_Average = get-content -path $testFN.FullName
    $global:CPU_Average | Measure-Object -Average | select -ExpandProperty Average | Write-Host
    Remove-Job -Name MyJob
}

【问题讨论】:

  • 我猜测Job 已添加,但尚未开始执行(即State 尚未更改为Running)。创建Job 时,您将放弃处理Scriptblock 的调度。由于您依赖于等到Job 开始执行,您难道不能像Start-ResourceMonitor 中的最后一行那样循环休眠直到JobState 更改为Running
  • @robert.westerlund 我已经尝试了您的建议,但得到了相同的结果。出于调试目的(仅限本地版本),我在停止之前在 Stop-ResourceMonitor 中输出作业状态 - 到目前为止,在我的所有运行中,状态一直在运行。
  • 是的,但是Job 可能在您停止它之前开始运行,即在您执行实际测试之后。如果您在执行实际测试之前输出作业的状态,我猜它不在Running 状态。同样,我只是在猜测,因为我不确定您如何确定“脚本块并不总是被执行”。
  • @robert.westerlund 澄清 - 除了我自己的调试版本状态输出之外,我还按照您的建议在 Start-ResourceMonitor 中添加了睡眠循环,并得到了相同的结果。确定脚本块未执行的一种方法是检查 C:\TEMP 文件夹中是否有应为每次运行创建的新文件。
  • 只是为了确保我理解,您尝试包含的睡眠循环是否放在紧跟$res = Start-Job ... 之后的行上,并且看起来类似于while ($res.State -ne 'Running'){ Start-Sleep -Milliseconds 500 }?另外,您的测试过程运行多长时间?我猜它至少运行了几秒钟,这个猜测正确吗?请记住,Get-WmiObject -ComputerName ... 也可能需要很短的时间才能获得响应,因此,如果测试在 Job 开始之前完成或比 Get-WmiObject 调用完成更快,您将不会得到写入文件。

标签: powershell cpu-usage powershell-3.0 scriptblock


【解决方案1】:

根本问题是测试运行了 2 到 60 秒之间的任何时间,并且 Get-WmiObject 运行时间比测试运行时间长,因此使用收集的指标创建文件的代码是'不为那些运行执行。
添加一个等待循环,在启动作业后(while 和 sleep)使作业真正开始运行并且要创建的文件解决了这个问题。
问题中的代码也已使用解决方案进行了更新。

【讨论】:

    猜你喜欢
    • 2019-11-22
    • 1970-01-01
    • 1970-01-01
    • 2018-10-07
    • 2021-03-28
    • 2011-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多