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 ) 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 * 15) 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 15) 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 15 Seconds" -PercentComplete 0 $RandomTest = & "$ExeFolder\diskspd.exe" -b4k -d10 -t1 -O32 -r -W2 -C2 -w0 -Z -c1G -Su "$($DLetter):\Integris\PowerShell Module\Get-DiskPerformance\Temp\test.dat" $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 15) Write-Progress -ID 3 -Activity "Running Disk Benchmark Tests" -Status "25% - Random Write - About 15 Seconds" -PercentComplete 25 $Random4kWrite = & "$ExeFolder\diskspd.exe" -b4k -d10 -t1 -O32 -r -W2 -C2 -w100 -Z -c1G -Su "$($DLetter):\Integris\PowerShell Module\Get-DiskPerformance\Temp\test.dat" $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 15) Write-Progress -ID 3 -Activity "Running Disk Benchmark Tests" -Status "50% - Sequential Read - About 15 Seconds" -PercentComplete 50 $Sequential1MBRead = & "$ExeFolder\diskspd.exe" -b1M -d10 -t1 -O8 -s -W2 -C2 -w0 -Z -c1G -Su "$($DLetter):\Integris\PowerShell Module\Get-DiskPerformance\Temp\test.dat" $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 15) Write-Progress -ID 3 -Activity "Running Disk Benchmark Tests" -Status "75% - Sequential Write - About 15 Seconds" -PercentComplete 75 ## Sequential Write $Sequential1MBWrite = & "$ExeFolder\diskspd.exe" -b1M -d10 -t1 -O8 -s -W2 -C2 -w100 -Z -c1G -Su "$($DLetter):\Integris\PowerShell Module\Get-DiskPerformance\Temp\test.dat" $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 += " | " $ExportPath += "RW$($RandomWriteMBs.ToString().PadLeft(4," "))" $ExportPath += " | " $ExportPath += "SR$($SequentialReadMBs.ToString().PadLeft(5," "))" $ExportPath += " | " $ExportPath += "SW$($SequentialWriteMBs.ToString().PadLeft(5," "))" $ExportPath += " | " $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 } |