92 lines
4.5 KiB
PowerShell
92 lines
4.5 KiB
PowerShell
# diag2.ps1 - полное чтение библиотек игр: ловим сбойные и "медленные" файлы
|
||
# Запускать, если diag1 не дал однозначного ответа. Время: 10-25 мин на ~150 ГБ SATA SSD.
|
||
# Запуск: powershell -NoProfile -ExecutionPolicy Bypass -File C:\diag2.ps1
|
||
|
||
$ErrorActionPreference = 'Continue'
|
||
$out = "$env:USERPROFILE\Desktop\diag2.txt"
|
||
Start-Transcript -Path $out -Force | Out-Null
|
||
|
||
# Порог "медленного" чтения. Для SATA SSD норма 300-550 МБ/с.
|
||
# Ниже 80 МБ/с на крупном файле = контроллер уходит в ретраи (потеря заряда в ячейках).
|
||
$SLOW_MBS = 80
|
||
$MIN_MB_FOR_SPEED = 8 # файлы мельче не оцениваем по скорости - оверхед искажает
|
||
|
||
$libs = @()
|
||
foreach ($drv in (Get-Volume | Where-Object { $_.DriveLetter -and $_.FileSystem -eq 'NTFS' }).DriveLetter) {
|
||
foreach ($cand in @("${drv}:\steam\steamapps\common", "${drv}:\SteamLibrary\steamapps\common", "${drv}:\Program Files (x86)\Steam\steamapps\common")) {
|
||
if (Test-Path $cand) { $libs += $cand }
|
||
}
|
||
}
|
||
"Библиотеки: $($libs -join ', ')"
|
||
|
||
# Проверяем проблемные игры; если их нет - всю библиотеку
|
||
$targets = @()
|
||
foreach ($l in $libs) {
|
||
$targets += Get-ChildItem $l -Directory -ErrorAction SilentlyContinue |
|
||
Where-Object { $_.Name -match 'Counter-Strike|Tsushima|Rome|Serious Sam' }
|
||
}
|
||
if (-not $targets) { $targets = $libs | ForEach-Object { Get-Item $_ } }
|
||
"Проверяю: $(($targets | ForEach-Object { $_.Name }) -join ' | ')`n"
|
||
|
||
$files = $targets | ForEach-Object { Get-ChildItem $_.FullName -Recurse -File -ErrorAction SilentlyContinue }
|
||
$totalGB = [math]::Round(($files | Measure-Object -Sum Length).Sum / 1GB, 1)
|
||
"Файлов: $($files.Count), объём: $totalGB ГБ`n"
|
||
|
||
$buf = New-Object byte[] 4194304
|
||
$bad = @(); $slow = @(); $i = 0
|
||
$swAll = [Diagnostics.Stopwatch]::StartNew()
|
||
|
||
foreach ($f in $files) {
|
||
$i++
|
||
if ($i % 200 -eq 0) { Write-Progress -Activity "Чтение" -Status "$i / $($files.Count)" -PercentComplete ($i * 100 / $files.Count) }
|
||
try {
|
||
$fs = [IO.File]::Open($f.FullName, 'Open', 'Read', 'Read')
|
||
$sw = [Diagnostics.Stopwatch]::StartNew()
|
||
$total = 0
|
||
while (($n = $fs.Read($buf, 0, $buf.Length)) -gt 0) { $total += $n }
|
||
$sw.Stop(); $fs.Close()
|
||
$mb = $total / 1MB
|
||
if ($mb -ge $MIN_MB_FOR_SPEED -and $sw.Elapsed.TotalSeconds -gt 0) {
|
||
$spd = $mb / $sw.Elapsed.TotalSeconds
|
||
if ($spd -lt $SLOW_MBS) {
|
||
$slow += [pscustomobject]@{ MBs = [math]::Round($spd, 1); MB = [math]::Round($mb, 1); Path = $f.FullName }
|
||
"SLOW {0,7:N1} MB/s {1,8:N1} MB {2}" -f $spd, $mb, $f.FullName
|
||
}
|
||
}
|
||
} catch {
|
||
$bad += [pscustomobject]@{ Path = $f.FullName; Err = $_.Exception.Message }
|
||
"FAIL $($f.FullName)`n -> $($_.Exception.Message)"
|
||
}
|
||
}
|
||
$swAll.Stop()
|
||
Write-Progress -Activity "Чтение" -Completed
|
||
|
||
"`n" + ('=' * 70)
|
||
"ИТОГ: прочитано $totalGB ГБ за $([math]::Round($swAll.Elapsed.TotalMinutes,1)) мин"
|
||
"Средняя скорость: $([math]::Round($totalGB * 1024 / $swAll.Elapsed.TotalSeconds, 1)) МБ/с"
|
||
"Ошибок чтения: $($bad.Count)"
|
||
"Медленных файлов (<$SLOW_MBS МБ/с): $($slow.Count)"
|
||
('=' * 70)
|
||
|
||
if ($bad) {
|
||
"`n--- ФАЙЛЫ С ОШИБКОЙ ЧТЕНИЯ (прямое доказательство сбойных секторов):"
|
||
$bad | Format-List
|
||
}
|
||
if ($slow) {
|
||
"`n--- ТОП-30 МЕДЛЕННЫХ (ретраи контроллера / потеря заряда в ячейках):"
|
||
$slow | Sort-Object MBs | Select-Object -First 30 | Format-Table -AutoSize
|
||
}
|
||
if (-not $bad -and -not $slow) {
|
||
"`nЧисто: все файлы читаются на полной скорости. Версия про накопитель слабеет -"
|
||
"переходим к питанию и драйверу (стресс GPU с логом HWiNFO)."
|
||
}
|
||
|
||
"`n--- SMART ПОСЛЕ ПРОГОНА (сравнить C5/05/BB с diag1: рост = диск сыплется прямо сейчас)"
|
||
$sm = "C:\Program Files\smartmontools\bin\smartctl.exe"
|
||
if (Test-Path $sm) {
|
||
& $sm --scan 2>&1 | ForEach-Object { if ($_ -match '^(\S+)\s') { "`n=== $($Matches[1])"; & $sm -A $Matches[1] 2>&1 } }
|
||
}
|
||
|
||
Stop-Transcript | Out-Null
|
||
Write-Host "`nОтчёт сохранён: $out" -ForegroundColor Green
|