Question

Context:
I want to run a test, and while it is running to gather CPU utilization. Basically, when I start the test I also want to start collecting data for CPU utilization, at the end of the test I also want to stop collecting data for CPU utilization (and average it afterwards).
Using PowerShell 3 on a Win7

Approach:
At the beginning of the test I added a function that starts a background job. The background job executes a scriptblock that runs a 'while ($true)' loop that collects the Average CPU utilization and saves it to a file. At the end of the test I read the file, average the collected data and stop and remove the job.

Problems:
For the current approach, the scriptblock doesn't always get executed, and no new data gets gathered. If I run the test several times, the scriptblock gets executed (in one of the runs) - I can't think of anything that would be relevant or this behavior. Also the scriptblock always gets executed if I use breakpoints anywhere in the test.
Can't think of another approach.

Answers desired:
1. Why isn't the script block being executed? and how to get it to execute?
2. Is there another way to collect resource data for the duration of the test?

Please note that the code has been through various try and fail runs and is no longer 'pretty'.
Code:

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
}
Was it helpful?

Solution

The underlying problem was that the test was running for anywhere between 2 and 60 seconds, and there where runs where the Get-WmiObject was taking longer than the test run, and thus the code for creating the file with the collected metrics wasn't executed for those runs.
Adding a wait loop, after starting the job, (while and sleep) for the job to actually start running and the files to get created solved the problem.
The code from the question has also been updated with the solution.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top