diff --git a/diag2.ps1 b/diag2.ps1 new file mode 100644 index 0000000..3e5b59d --- /dev/null +++ b/diag2.ps1 @@ -0,0 +1,91 @@ +# 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