Files
Qt_DesktopPet/internal/qa/scripts/perf_sample.ps1
T

171 lines
5.6 KiB
PowerShell

param(
[string]$ProcessName = "QtDesktopPet",
[Alias("Pid")]
[int]$ProcessId = 0,
[ValidateRange(1, 86400)]
[int]$IntervalSeconds = 5,
[ValidateRange(1, 604800)]
[int]$DurationSeconds = 300,
[string]$Scenario = "unspecified",
[string]$OutputPath = "reports/perf"
)
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
function Resolve-TargetProcess {
param(
[string]$Name,
[int]$Id
)
if ($Id -gt 0) {
return Get-Process -Id $Id -ErrorAction SilentlyContinue
}
$processes = @(Get-Process -Name $Name -ErrorAction SilentlyContinue)
if ($processes.Count -eq 0) {
return $null
}
if ($processes.Count -gt 1) {
Write-Warning "Multiple processes named '$Name' were found. Sampling PID $($processes[0].Id). Use -Pid to target a specific process."
}
return $processes[0]
}
function Read-ProcessSnapshot {
param([System.Diagnostics.Process]$Process)
$path = ""
try { $path = $Process.Path } catch { $path = "" }
$responding = ""
try { $responding = $Process.Responding } catch { $responding = "" }
return [pscustomobject]@{
TimestampUtc = (Get-Date).ToUniversalTime().ToString("o")
Pid = $Process.Id
CpuSeconds = [double]($Process.CPU)
WorkingSetMB = [math]::Round($Process.WorkingSet64 / 1MB, 2)
PrivateMemoryMB = [math]::Round($Process.PrivateMemorySize64 / 1MB, 2)
HandleCount = $Process.HandleCount
ThreadCount = $Process.Threads.Count
Responding = $responding
Path = $path
}
}
function Resolve-OutputDirectory {
param([string]$Path)
if ([System.IO.Path]::IsPathRooted($Path)) {
return [System.IO.Path]::GetFullPath($Path)
}
$repoRoot = [System.IO.Path]::GetFullPath((Join-Path $PSScriptRoot "..\..\.."))
return [System.IO.Path]::GetFullPath((Join-Path $repoRoot $Path))
}
function New-OutputFilePath {
param(
[string]$Directory,
[string]$Name
)
if (-not (Test-Path -LiteralPath $Directory)) {
New-Item -ItemType Directory -Force -Path $Directory | Out-Null
}
$safeName = $Name -replace '[^a-zA-Z0-9._-]', '_'
$timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
return Join-Path $Directory "$timestamp-$safeName.csv"
}
$target = Resolve-TargetProcess -Name $ProcessName -Id $ProcessId
if ($null -eq $target) {
if ($ProcessId -gt 0) {
Write-Error "Process with PID $ProcessId was not found."
} else {
Write-Error "Process '$ProcessName' was not found. Start the app first or pass -Pid."
}
exit 1
}
$logicalProcessorCount = [math]::Max(1, [Environment]::ProcessorCount)
$outputDirectory = Resolve-OutputDirectory -Path $OutputPath
$outputFile = New-OutputFilePath -Directory $outputDirectory -Name "$Scenario-$($target.ProcessName)"
$sampleCount = [math]::Max(1, [math]::Ceiling($DurationSeconds / $IntervalSeconds))
Write-Host "Sampling scenario '$Scenario' for PID $($target.Id) ($($target.ProcessName)) every $IntervalSeconds seconds for up to $DurationSeconds seconds."
Write-Host "Output: $outputFile"
$previousSnapshot = Read-ProcessSnapshot -Process $target
$previousTime = Get-Date
$firstRow = [pscustomobject]@{
Scenario = $Scenario
SampleIndex = 0
TimestampUtc = $previousSnapshot.TimestampUtc
Pid = $previousSnapshot.Pid
CpuPercent = 0
WorkingSetMB = $previousSnapshot.WorkingSetMB
PrivateMemoryMB = $previousSnapshot.PrivateMemoryMB
HandleCount = $previousSnapshot.HandleCount
ThreadCount = $previousSnapshot.ThreadCount
Responding = $previousSnapshot.Responding
Path = $previousSnapshot.Path
Status = "running"
}
$firstRow | Export-Csv -Path $outputFile -NoTypeInformation -Encoding UTF8
for ($index = 1; $index -le $sampleCount; $index++) {
Start-Sleep -Seconds $IntervalSeconds
$currentProcess = Get-Process -Id $target.Id -ErrorAction SilentlyContinue
if ($null -eq $currentProcess) {
[pscustomobject]@{
Scenario = $Scenario
SampleIndex = $index
TimestampUtc = (Get-Date).ToUniversalTime().ToString("o")
Pid = $target.Id
CpuPercent = ""
WorkingSetMB = ""
PrivateMemoryMB = ""
HandleCount = ""
ThreadCount = ""
Responding = ""
Path = $previousSnapshot.Path
Status = "exited"
} | Export-Csv -Path $outputFile -NoTypeInformation -Encoding UTF8 -Append
Write-Warning "Process $($target.Id) exited. Sampling stopped."
break
}
$currentSnapshot = Read-ProcessSnapshot -Process $currentProcess
$currentTime = Get-Date
$elapsedSeconds = [math]::Max(0.001, ($currentTime - $previousTime).TotalSeconds)
$cpuPercent = (($currentSnapshot.CpuSeconds - $previousSnapshot.CpuSeconds) / $elapsedSeconds) * 100 / $logicalProcessorCount
if ($cpuPercent -lt 0) { $cpuPercent = 0 }
[pscustomobject]@{
Scenario = $Scenario
SampleIndex = $index
TimestampUtc = $currentSnapshot.TimestampUtc
Pid = $currentSnapshot.Pid
CpuPercent = [math]::Round($cpuPercent, 2)
WorkingSetMB = $currentSnapshot.WorkingSetMB
PrivateMemoryMB = $currentSnapshot.PrivateMemoryMB
HandleCount = $currentSnapshot.HandleCount
ThreadCount = $currentSnapshot.ThreadCount
Responding = $currentSnapshot.Responding
Path = $currentSnapshot.Path
Status = "running"
} | Export-Csv -Path $outputFile -NoTypeInformation -Encoding UTF8 -Append
$previousSnapshot = $currentSnapshot
$previousTime = $currentTime
}
Write-Host "Sampling finished: $outputFile"