param( [string]$Name = 'TrufFreezeCounters', [string]$OutputRoot = 'D:\truf\runtime\freeze-diagnostics' ) $ErrorActionPreference = 'Stop' throw 'Docker development copy: runtime control is disabled until container isolation is ready. See DOCKER_MIGRATION.md.' function Start-FallbackMonitor { $monitor = Join-Path $PSScriptRoot 'monitor_runtime_lag.ps1' if (-not (Test-Path -LiteralPath $monitor)) { throw 'Fallback freeze monitor script is absent' } Start-Process ` -FilePath "$env:SystemRoot\System32\WindowsPowerShell\v1.0\powershell.exe" ` -ArgumentList @( '-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', $monitor, '-OutputPath', (Join-Path $OutputRoot 'freeze-fallback-v3.csv'), '-IntervalSeconds', '5' ) ` -WindowStyle Hidden | Out-Null } if (-not (Test-Path -LiteralPath $OutputRoot)) { New-Item -ItemType Directory -Path $OutputRoot | Out-Null } function Read-CounterTable([string]$Language) { $values = (Get-ItemProperty -LiteralPath "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\$Language").Counter $result = @{} for ($index = 0; $index -lt $values.Count; $index += 2) { $result[[int]$values[$index]] = $values[$index + 1] } return $result } $english = Read-CounterTable '009' $localized = Read-CounterTable '019' $indexByEnglishName = @{} foreach ($entry in $english.GetEnumerator()) { $indexByEnglishName[[string]$entry.Value] = [int]$entry.Key } function Counter-Path([string]$Object, [string]$Counter, [string]$Instance = '') { if (-not $indexByEnglishName.ContainsKey($Object) -or -not $indexByEnglishName.ContainsKey($Counter)) { return $null } $objectName = $localized[$indexByEnglishName[$Object]] $counterName = $localized[$indexByEnglishName[$Counter]] if (-not $objectName -or -not $counterName) { return $null } if ($Instance) { return "\$objectName($Instance)\$counterName" } return "\$objectName\$counterName" } $requested = @( @('Processor', '% Processor Time', '_Total'), @('System', 'Processor Queue Length', ''), @('System', 'Context Switches/sec', ''), @('System', 'Processes', ''), @('System', 'Threads', ''), @('Memory', 'Available MBytes', ''), @('Memory', '% Committed Bytes In Use', ''), @('Memory', 'Pages Input/sec', ''), @('Memory', 'Page Reads/sec', ''), @('Memory', 'Pool Nonpaged Bytes', ''), @('Paging File', '% Usage', '_Total'), @('PhysicalDisk', 'Current Disk Queue Length', '*'), @('PhysicalDisk', 'Avg. Disk sec/Transfer', '*'), @('PhysicalDisk', 'Disk Read Bytes/sec', '*'), @('PhysicalDisk', 'Disk Write Bytes/sec', '*'), @('PhysicalDisk', 'Disk Reads/sec', '*'), @('PhysicalDisk', 'Disk Writes/sec', '*'), @('Process', '% Processor Time', '*'), @('Process', 'Private Bytes', '*'), @('Process', 'Working Set', '*'), @('Process', 'Handle Count', '*'), @('Process', 'Thread Count', '*'), @('Process', 'IO Read Bytes/sec', '*'), @('Process', 'IO Write Bytes/sec', '*'), @('Process', 'Page Faults/sec', '*'), @('GPU Engine', 'Utilization Percentage', '*'), @('GPU Process Memory', 'Local Usage', '*'), @('GPU Process Memory', 'Non Local Usage', '*') ) $counters = @( foreach ($definition in $requested) { $path = Counter-Path $definition[0] $definition[1] $definition[2] if ($path) { $path } } ) if (-not $counters.Count) { throw 'No localized performance counters could be resolved' } & logman.exe query $Name *> $null $exists = $LASTEXITCODE -eq 0 if (-not $exists) { & logman.exe create counter $Name ` -f bincirc ` -max 512 ` -si 00:00:01 ` -o (Join-Path $OutputRoot 'freeze-counters') ` -c $counters *> $null if ($LASTEXITCODE -ne 0) { Start-FallbackMonitor return } } & logman.exe start $Name *> $null if ($LASTEXITCODE -ne 0) { & logman.exe query $Name *> $null if ($LASTEXITCODE -ne 0) { Start-FallbackMonitor return } }