Public/Diagnostics/Get-DiskPerformance.ps1
<#
Copyright © 2024 Integris. For internal company use only. All rights reserved. #> FUNCTION Get-DiskPerformance { <# .SYNOPSIS Performs disk performance benchmarking on specified drives. .DESCRIPTION This function benchmarks the performance of specified disk drives using the Microsoft DiskSpd tool. It measures random and sequential read/write speeds and provides a rating based on the results. .PARAMETER DriveLetter Specifies the drive letters to benchmark. Default is "C". .PARAMETER All If specified, benchmarks all available drives. .EXAMPLE Get-DiskPerformance -DriveLetter @("C", "D") This command benchmarks the performance of the C and D drives. .EXAMPLE Get-DiskPerformance -All This command benchmarks the performance of all available drives. .NOTES This function requires the DiskSpd tool to be installed in the specified directory and may need to be run with elevated privileges. #> [CmdletBinding(DefaultParameterSetName='Specific')] PARAM ( [Parameter(ParameterSetName = 'Specific')] [String[]]$DriveLetter = @("C"), [Parameter(ParameterSetName = 'All')] [Switch]$All = $False, [Switch]$Quick = $False ) IF ($Quick) { $Duration = 4 $WarmupTime = 2 $CooldownTime = 0 } ELSE { $Duration = 10 $WarmupTime = 3 $CooldownTime = 2 } IF (!(Test-AdministratorElevation)) { RETURN } IF (!(Test-IntegrisFileDependency -RootPath "$ModuleUtilityDir\DiskSpd" -ChildPath "\x86\diskspd.exe" -DownloadURL "https://aka.ms/getdiskspd" -Unzip -Force)) { RETURN } IF ($All -eq $True) { $DriveLetter = (Get-Volume | Where-Object { $_.DriveLetter.Length -eq 1 }).DriveLetter } $Results = @() $ProgressCountCurrent = 0 $ProgressCountTotal = $DriveLetter.Count * 4 $ProgressPercent = "0" $TimeLeft = New-Timespan -Seconds ($ProgressCountTotal * $($Duration + $WarmupTime + $CooldownTime)) FOREACH ($DLetter in $DriveLetter) { $ProgressPercent = [MATH]::Round(($ProgressCountCurrent / $ProgressCountTotal * 100),0) Write-Progress -ID 15 -Activity "Total Progress" -Status "$($ProgressPercent)% - Time Left: ~$($TimeLeft.Hours):$($TimeLeft.Minutes.ToString().Padleft(2,"0")):$($TimeLeft.Seconds.ToString().Padleft(2,"0"))" -PercentComplete $ProgressPercent $ProgressCountCurrent++ $TimeLeft = $TimeLeft - (New-TimeSpan -Seconds $Duration) IF ($null -eq (Get-Volume -DriveLetter $DLetter -ErrorAction SilentlyContinue)) { Write-Warning "Drive letter $($DLetter) not found."; RETURN } $ExeFolder = "$ModuleUtilityDir\DiskSpd\x86" $IOType = "" $AccessType = "" $ResultRating = 0 $ResultRatingString = "" Write-Progress -ID 3 -Activity "Running Disk Benchmark Tests" -Status "0% - Random Read - About $Duration Seconds" -PercentComplete 0 ## Random Readd $Params = @("-b4k","-d$($Duration)","-t1","-O32","-r","-W$($WarmupTime)","-C$($CooldownTime)","-w0","-Z","-c1G","-Su","$($DLetter):\Integris\PowerShell Module\Get-DiskPerformance\Temp\test.dat") $RandomTest = & "$ExeFolder\diskspd.exe" $Params $RandomTestResults = $RandomTest[-15] | convertfrom-csv -Delimiter "|" -Header Bytes,IO,Mib,IOPS,File | Select-Object IO,MIB,IOPs [int]$RandomMBs = $RandomTestResults.Mib IF ($RandomMBs -gt 200) { $ResultRating = 9; $ResultRatingString = "Crazy Fast" } ELSEIF ($RandomMBs -gt 100) { $ResultRating = 8; $ResultRatingString = "Extremely Fast" } ELSEIF ($RandomMBs -gt 60) { $ResultRating = 7; $ResultRatingString = "Very Fast" } ELSEIF ($RandomMBs -gt 30) { $ResultRating = 6; $ResultRatingString = "Fast" } ELSEIF ($RandomMBs -gt 15) { $ResultRating = 5; $ResultRatingString = "Good" } ELSEIF ($RandomMBs -gt 8) { $ResultRating = 4; $ResultRatingString = "Acceptable" } ELSEIF ($RandomMBs -gt 3) { $ResultRating = 3; $ResultRatingString = "Slow" } ELSEIF ($RandomMBs -gt 1) { $ResultRating = 2; $ResultRatingString = "VerySlow" } ELSE { $ResultRating = 1; $ResultRatingString = "Extremely Slow" } $IOType = "Random" $AccessType = "Read" $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{ DriveLetter = $DLetter IOType = $IOType AccessType = $AccessType ResultMBs = [int]$RandomTestResults.Mib ResultIOPS = [int]$RandomTestResults.IOPS ResultRating = $ResultRating ResultRatingString = $ResultRatingString } $ProgressPercent = [MATH]::Round(($ProgressCountCurrent / $ProgressCountTotal * 100),0) Write-Progress -ID 15 -Activity "Total Progress" -Status "$($ProgressPercent)% - Time Left: ~$($TimeLeft.Hours):$($TimeLeft.Minutes.ToString().Padleft(2,"0")):$($TimeLeft.Seconds.ToString().Padleft(2,"0"))" -PercentComplete $ProgressPercent $ProgressCountCurrent++ $TimeLeft = $TimeLeft - (New-TimeSpan -Seconds $Duration) Write-Progress -ID 3 -Activity "Running Disk Benchmark Tests" -Status "25% - Random Write - About $Duration Seconds" -PercentComplete 25 ## Random Write $Params = @("-b4k","-d$($Duration)","-t1","-O32","-r","-W$($WarmupTime)","-C$($CooldownTime)","-w100","-Z","-c1G","-Su","$($DLetter):\Integris\PowerShell Module\Get-DiskPerformance\Temp\test.dat") $Random4kWrite = & "$ExeFolder\diskspd.exe" $Params $Random4kWriteResults = $Random4kWrite[-15] | convertfrom-csv -Delimiter "|" -Header Bytes,IO,Mib,IOPS,File | Select-Object IO,MIB,IOPs [int]$RandomWriteMBs = $Random4kWriteResults.Mib IF ($RandomWriteMBs -gt 200) { $ResultRating = 9; $ResultRatingString = "Crazy Fast" } ELSEIF ($RandomWriteMBs -gt 100) { $ResultRating = 8; $ResultRatingString = "Extremely Fast" } ELSEIF ($RandomWriteMBs -gt 60) { $ResultRating = 7; $ResultRatingString = "Very Fast" } ELSEIF ($RandomWriteMBs -gt 30) { $ResultRating = 6; $ResultRatingString = "Fast" } ELSEIF ($RandomWriteMBs -gt 15) { $ResultRating = 5; $ResultRatingString = "Good" } ELSEIF ($RandomWriteMBs -gt 8) { $ResultRating = 4; $ResultRatingString = "Acceptable" } ELSEIF ($RandomWriteMBs -gt 3) { $ResultRating = 3; $ResultRatingString = "Slow" } ELSEIF ($RandomWriteMBs -gt 1) { $ResultRating = 2; $ResultRatingString = "VerySlow" } ELSE { $ResultRating = 1; $ResultRatingString = "Extremely Slow" } $IOType = "Random" $AccessType = "Write" $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{ DriveLetter = $DLetter IOType = $IOType AccessType = $AccessType ResultMBs = [int]$Random4kWriteResults.Mib ResultIOPS = [int]$Random4kWriteResults.IOPS ResultRating = $ResultRating ResultRatingString = $ResultRatingString } $ProgressPercent = [MATH]::Round(($ProgressCountCurrent / $ProgressCountTotal * 100),0) Write-Progress -ID 15 -Activity "Total Progress" -Status "$($ProgressPercent)% - Time Left: ~$($TimeLeft.Hours):$($TimeLeft.Minutes.ToString().Padleft(2,"0")):$($TimeLeft.Seconds.ToString().Padleft(2,"0"))" -PercentComplete $ProgressPercent $ProgressCountCurrent++ $TimeLeft = $TimeLeft - (New-TimeSpan -Seconds $Duration) Write-Progress -ID 3 -Activity "Running Disk Benchmark Tests" -Status "50% - Sequential Read - About $Duration Seconds" -PercentComplete 50 ## Sequential Read $Params = @("-b1M","-d$($Duration)","-t1","-O8","-s","-W$($WarmupTime)","-C$($CooldownTime)","-w0","-Z","-c1G","-Su","$($DLetter):\Integris\PowerShell Module\Get-DiskPerformance\Temp\test.dat") $Sequential1MBRead = & "$ExeFolder\diskspd.exe" $Params $Sequential1MBReadResults = $Sequential1MBRead[-8] | convertfrom-csv -Delimiter "|" -Header Bytes,IO,Mib,IOPS,File | Select-Object IO,MIB,IOPs [int]$SequentialReadMBs = $Sequential1MBReadResults.Mib IF ($SequentialReadMBs -gt 1500) { $ResultRating = 9; $ResultRatingString = "Crazy Fast" } ELSEIF ($SequentialReadMBs -gt 900) { $ResultRating = 8; $ResultRatingString = "Extremely Fast" } ELSEIF ($SequentialReadMBs -gt 450) { $ResultRating = 7; $ResultRatingString = "Very Fast" } ELSEIF ($SequentialReadMBs -gt 225) { $ResultRating = 6; $ResultRatingString = "Fast" } ELSEIF ($SequentialReadMBs -gt 150) { $ResultRating = 5; $ResultRatingString = "Good" } ELSEIF ($SequentialReadMBs -gt 90) { $ResultRating = 4; $ResultRatingString = "Acceptable" } ELSEIF ($SequentialReadMBs -gt 50) { $ResultRating = 3; $ResultRatingString = "Slow" } ELSEIF ($SequentialReadMBs -gt 25) { $ResultRating = 2; $ResultRatingString = "VerySlow" } ELSE { $ResultRating = 1; $ResultRatingString = "Extremely Slow" } $IOType = "Sequential" $AccessType = "Read" $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{ DriveLetter = $DLetter IOType = $IOType AccessType = $AccessType ResultMBs = [int]$Sequential1MBReadResults.Mib ResultIOPS = [int]$Sequential1MBReadResults.IOPS ResultRating = $ResultRating ResultRatingString = $ResultRatingString } $ProgressPercent = [MATH]::Round(($ProgressCountCurrent / $ProgressCountTotal * 100),0) Write-Progress -ID 15 -Activity "Total Progress" -Status "$($ProgressPercent)% - Time Left: ~$($TimeLeft.Hours):$($TimeLeft.Minutes.ToString().Padleft(2,"0")):$($TimeLeft.Seconds.ToString().Padleft(2,"0"))" -PercentComplete $ProgressPercent $ProgressCountCurrent++ $TimeLeft = $TimeLeft - (New-TimeSpan -Seconds $Duration) Write-Progress -ID 3 -Activity "Running Disk Benchmark Tests" -Status "75% - Sequential Write - About $Duration Seconds" -PercentComplete 75 ## Sequential Write $Params = @("-b1M","-d$($Duration)","-t1","-O8","-s","-W$($WarmupTime)","-C$($CooldownTime)","-w100","-Z","-c1G","-Su","$($DLetter):\Integris\PowerShell Module\Get-DiskPerformance\Temp\test.dat") $Sequential1MBWrite = & "$ExeFolder\diskspd.exe" $Params $Sequential1MBWriteResults = $Sequential1MBWrite[-15] | convertfrom-csv -Delimiter "|" -Header Bytes,IO,Mib,IOPS,File | Select-Object IO,MIB,IOPs [int]$SequentialWriteMBs = $Sequential1MBWriteResults.Mib IF ($SequentialWriteMBs -gt 1500) { $ResultRating = 9; $ResultRatingString = "Crazy Fast" } ELSEIF ($SequentialWriteMBs -gt 900) { $ResultRating = 8; $ResultRatingString = "Extremely Fast" } ELSEIF ($SequentialWriteMBs -gt 450) { $ResultRating = 7; $ResultRatingString = "Very Fast" } ELSEIF ($SequentialWriteMBs -gt 225) { $ResultRating = 6; $ResultRatingString = "Fast" } ELSEIF ($SequentialWriteMBs -gt 150) { $ResultRating = 5; $ResultRatingString = "Good" } ELSEIF ($SequentialWriteMBs -gt 90) { $ResultRating = 4; $ResultRatingString = "Acceptable" } ELSEIF ($SequentialWriteMBs -gt 50) { $ResultRating = 3; $ResultRatingString = "Slow" } ELSEIF ($SequentialWriteMBs -gt 25) { $ResultRating = 2; $ResultRatingString = "VerySlow" } ELSE { $ResultRating = 1; $ResultRatingString = "Extremely Slow" } Write-Progress -ID 3 -Activity "Running Disk Benchmark Tests" -Status "100% - Finalizing Results" -PercentComplete 100 -Completed $IOType = "Sequential" $AccessType = "Write" $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{ DriveLetter = $DLetter IOType = $IOType AccessType = $AccessType ResultMBs = [int]$Sequential1MBWriteResults.Mib ResultIOPS = [int]$Sequential1MBWriteResults.IOPS ResultRating = $ResultRating ResultRatingString = $ResultRatingString } [string]$ExportPath = "$ModuleExportDir\Get-DiskPerformance\Results\" MKDIR $ExportPath -ErrorAction SilentlyContinue | Out-Null $ExportPath += "$($DLetter) Volume" $ExportPath += " - " $ExportPath += "RR$($RandomMBs.ToString().PadLeft(4," "))" $ExportPath += " I " $ExportPath += "RW$($RandomWriteMBs.ToString().PadLeft(4," "))" $ExportPath += " I " $ExportPath += "SR$($SequentialReadMBs.ToString().PadLeft(5," "))" $ExportPath += " I " $ExportPath += "SW$($SequentialWriteMBs.ToString().PadLeft(5," "))" $ExportPath += " I " $ExportPath += (Get-Date).ToString("yyy_MM_dd HH_mm_ss") $ExportPath += ".csv" $Results | Select-Object DriveLetter, IOType, AccessType, ResultMBs, ResultRating, ResultRatingString | Export-CSV -Path $ExportPath -Force -NoTypeInformation } Write-Progress -ID 15 -Activity "Total Progress" -Status "100%" -PercentComplete 100 RETURN $Results | Select-Object DriveLetter, IOType, AccessType, ResultMBs, ResultRating, ResultRatingString } |