Moved from wayBetter for X; an app passes its own origin, process name, scripts and fixtures.
57 lines
2.6 KiB
PowerShell
57 lines
2.6 KiB
PowerShell
param(
|
|
[Parameter(Mandatory = $true)][int]$AppPid,
|
|
[Parameter(Mandatory = $true)][string]$OutputPath,
|
|
[int]$Seconds = 90,
|
|
[int]$IntervalSeconds = 2,
|
|
[int]$AbortAtWorkingSetMB = 0,
|
|
[string]$ExpectedExecutable = ''
|
|
)
|
|
|
|
# Independent telemetry for native-webview-stress.mjs. Follow only descendants of the
|
|
# isolated app PID; a hung shell CDP target cannot stop this watcher from recording CPU.
|
|
$previousCpu = @{}
|
|
$watch = [System.Diagnostics.Stopwatch]::StartNew()
|
|
while ($watch.Elapsed.TotalSeconds -lt $Seconds) {
|
|
$all = @(Get-CimInstance Win32_Process | Select-Object ProcessId, ParentProcessId)
|
|
$ids = @($AppPid)
|
|
do {
|
|
$children = @($all | Where-Object {
|
|
$ids -contains $_.ParentProcessId -and $ids -notcontains $_.ProcessId
|
|
} | Select-Object -ExpandProperty ProcessId)
|
|
$ids += $children
|
|
} while ($children.Count -gt 0)
|
|
|
|
$processes = @(Get-Process -Id $ids -ErrorAction SilentlyContinue)
|
|
if (-not ($processes | Where-Object Id -EQ $AppPid)) { break }
|
|
$rows = @($processes | ForEach-Object {
|
|
$cpu = if ($null -eq $_.CPU) { 0 } else { [double]$_.CPU }
|
|
$before = if ($previousCpu.ContainsKey($_.Id)) { $previousCpu[$_.Id] } else { $cpu }
|
|
$previousCpu[$_.Id] = $cpu
|
|
[pscustomobject]@{
|
|
pid = $_.Id
|
|
name = $_.ProcessName
|
|
cpuDeltaSeconds = [math]::Round($cpu - $before, 3)
|
|
cpuTotalSeconds = [math]::Round($cpu, 3)
|
|
workingSetMB = [math]::Round($_.WorkingSet64 / 1MB)
|
|
privateMB = [math]::Round($_.PrivateMemorySize64 / 1MB)
|
|
}
|
|
} | Sort-Object cpuDeltaSeconds -Descending)
|
|
$totalWorkingSetMB = ($rows | Measure-Object workingSetMB -Sum).Sum
|
|
[pscustomobject]@{
|
|
elapsedSeconds = [math]::Round($watch.Elapsed.TotalSeconds, 2)
|
|
processCount = $rows.Count
|
|
totalCpuDeltaSeconds = [math]::Round(($rows | Measure-Object cpuDeltaSeconds -Sum).Sum, 3)
|
|
totalWorkingSetMB = $totalWorkingSetMB
|
|
top = @($rows | Select-Object -First 8)
|
|
} | ConvertTo-Json -Depth 5 -Compress | Add-Content -LiteralPath $OutputPath
|
|
if ($AbortAtWorkingSetMB -gt 0 -and $totalWorkingSetMB -ge $AbortAtWorkingSetMB) {
|
|
$app = Get-CimInstance Win32_Process -Filter "ProcessId=$AppPid"
|
|
if ($app -and $ExpectedExecutable -and $app.ExecutablePath -ieq $ExpectedExecutable) {
|
|
[pscustomobject]@{ event = 'memory-abort'; appPid = $AppPid; workingSetMB = $totalWorkingSetMB } |
|
|
ConvertTo-Json -Compress | Add-Content -LiteralPath $OutputPath
|
|
Stop-Process -Id $AppPid -Force
|
|
}
|
|
break
|
|
}
|
|
Start-Sleep -Seconds $IntervalSeconds
|
|
}
|