Introduction
One part in testing a VPS is to read and write data to the disk. The other parts are usually the upload/download speed and CPU usage. We have all seen these statistics when reading reviews on providers.
Being a part of communitys where the focus lays in the Linux world, the (in)famous dd command is used on most occasions to measure disk speeds. Even if the accuracy of these types of sequential reading and writing tests on a server are debated, as opposed to real life experience where random reading and writing data all over the disk. That discussion is not the intended direction of this article so I’ll leave it to another article at a later time.
For those of you that doesn’t know of the dd command and wonder what I’m writing about. This is the command that will give you a hint of how fast (or slow) your disk is:
1 |
dd if=/dev/zero of=test bs=64k count=16k conv=fdatasync; unlink test |
When ran on a Linux server you should get a result like this (Time and speed may vary):
1 2 3 |
16384+0 records in 16384+0 records out 1073741824 bytes (1.1 GB) copied, 10.4723 s, 103 MB/s |
Windows Users, What to use?
Since dd only works on Linux Operating Systems, what would a Windows user use to measure his/her server when it comes to disk speed? I have seen that same question more and more frequent on some of the forums I visit and to my findings the tool that comes closest is the SQLIO.EXE utility by Microsoft.
Despite its name, sqlio is not part of SQL Server, yet it can be an invaluable tool for determining whether the disk drives slated to support SQL Server can meet the system’s I/O needs. The tool lets you push the limits of your disk subsystem in order to determine the hardware’s I/O capacity and to identify performance-related issues before using the server in production.
The upside of this tool is that you can use it to test a variety of disk subsystems, including direct attached storage, network attached storage, and storage area networks.
Download this utility directly from Microsoft using this link and run the msi file on the server you would like to test. You could also run the installation on your local computer and then copy the sqlio.exe file to the server. There is no need for installation except to package all the files that comes with the utility.
Included in the msi package is a README.rtf file with an introduction to the utility and more important the param.txt that explains the configuration options when running this command.
I won’t get into much detail about this utility, instead I would like to introduce you to this Powershell wrapper which I find easier to use and will give you the output as a table or in a grid. You can measure the workload in two ways, IOPS or Transfer rate.
This Powershell wrapper is written by Mikael Nyström, Microsoft MVP. Link to his website is here.
The script is available for download here and full code is shown further down this page,
Prerequisite:
- Sqlio.exe must be in the same directory as the PowerShell script.
- PowerShell 3.0 must be installed
Example:
1 |
.\Measure-DiskPerformance.ps1 -TestFileName test.dat –TestFileSizeInGB 1 -TestFilepath C:\VMs -TestMode Get-LargeIO -FastMode True -RemoveTestFile True -OutputFormat Out-GridView |
Explanation:
-TestFileName test.dat
The name of the file, it will create the file using FSUTIL, but it checks if it exists and if it does it stops, you can override that with the –RemoveTestFile True
–TestFileSizeInGB 1
Size of the file, it has fixed values, use the TAB key to flip through them
-TestFilepath C:\VMs
The folder, can also be an UNC path, it will create the folder so it does not need to exist.
-TestMode Get-LargeIO
There is too test modes Get-LargeIO or Get-SmallIO, you use Get-LargeIO to measure the transfer rate and you use Get-SmallIO to measure IOPS
-FastMode True
Fastmode true runs each test for just 10 seconds, it gives you a hint, if you don’t set it or set it to false it will run for 60 sec (it will take a break for 10 sec between each run)
-RemoveTestFile True
Removes the test file if it exists
-OutputFormat Out-GridView
Choose between Out-Gridview or Format-Table
That is all to know about this script and utility.
This is the output I get when testing IOPS on a XEN HVM+PV that I have with Inception Hosting:
Don’t forget to press CTRL+C to stop the test when you have enough data.
Complete script in plain text for those of you that want to read it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
<# .Synopsis Short description .DESCRIPTION Long description .EXAMPLE Example of how to use this cmdlet .EXAMPLE Another example of how to use this cmdlet .INPUTS Inputs to this cmdlet (if any) .OUTPUTS Output from this cmdlet (if any) .NOTES Version 1.2 .COMPONENT The component this cmdlet belongs to .ROLE The role this cmdlet belongs to .FUNCTIONALITY The functionality that best describes this cmdlet #> Param( [parameter(mandatory=$False,HelpMessage='Name of test file')] [ValidateLength(2,30)] $TestFileName = "test.dat", [parameter(mandatory=$False,HelpMessage='Test file size in GB')] [ValidateSet('1','5','10','50','100','500','1000')] $TestFileSizeInGB = 1, [parameter(mandatory=$False,HelpMessage='Path to test folder')] [ValidateLength(3,254)] $TestFilepath = 'C:\Test', [parameter(mandatory=$True,HelpMessage='Test mode, use Get-SmallIO for IOPS and Get-LargeIO for MB/s ')] [ValidateSet('Get-SmallIO','Get-LargeIO')] $TestMode, [parameter(mandatory=$False,HelpMessage='Fast test mode or standard')] [ValidateSet('True','False')] $FastMode = 'True', [parameter(mandatory=$False,HelpMessage='Remove existing test file')] [ValidateSet('True','False')] $RemoveTestFile='False', [parameter(mandatory=$False,HelpMessage='Remove existing test file')] [ValidateSet('Out-GridView','Format-Table')] $OutputFormat='Out-GridView' ) Function New-TestFile{ $Folder = New-Item -Path $TestFilePath -ItemType Directory -Force -ErrorAction SilentlyContinue $TestFileAndPath = "$TestFilePath\$TestFileName" Write-Host "Checking for $TestFileAndPath" $FileExist = Test-Path $TestFileAndPath if ($FileExist -eq $True) { if ($RemoveTestFile -EQ 'True') { Remove-Item -Path $TestFileAndPath -Force } else { Write-Host 'File Exists, break' Break } } Write-Host 'Creating test file using fsutil.exe...' & cmd.exe /c FSUTIL.EXE file createnew $TestFileAndPath ($TestFileSizeInGB*1024*1024*1024) & cmd.exe /c FSUTIL.EXE file setvaliddata $TestFileAndPath ($TestFileSizeInGB*1024*1024*1024) } Function Remove-TestFile{ $TestFileAndPath = "$TestFilePath\$TestFileName" Write-Host "Checking for $TestFileAndPath" $FileExist = Test-Path $TestFileAndPath if ($FileExist -eq $True) { Write-Host 'File Exists, deleting' Remove-Item -Path $TestFileAndPath -Force -Verbose } } Function Get-SmallIO{ Write-Host 'Initialize for SmallIO...' 8..64 | % { $KBytes = '8' $Type = 'random' $b = "-b$KBytes"; $f = "-f$Type"; $o = "-o $_"; $Result = & $RunningFromFolder\sqlio.exe $Duration -kR $f $b $o -t4 -LS -BN "$TestFilePath\$TestFileName" Start-Sleep -Seconds 5 -Verbose $iops = $Result.Split("`n")[10].Split(':')[1].Trim() $mbs = $Result.Split("`n")[11].Split(':')[1].Trim() $latency = $Result.Split("`n")[14].Split(':')[1].Trim() $SeqRnd = $Result.Split("`n")[14].Split(':')[1].Trim() New-object psobject -property @{ Type = $($Type) SizeIOKBytes = $($KBytes) OutStandingIOs = $($_) IOPS = $($iops) MBSec = $($mbs) LatencyMS = $($latency) Target = $("$TestFilePath\$TestFileName") } } } Function Get-LargeIO{ $KBytes = '512' $Type = 'sequential' Write-Host 'Initialize for LargeIO...' Write-Host "Reading $KBytes Bytes in $Type mode using $TestFilePath\$TestFileName as target" 1..32 | % { $b = "-b$KBytes"; $f = "-f$Type"; $o = "-o $_"; $Result = & $RunningFromFolder\sqlio.exe $Duration -kR $f $b $o -t1 -LS -BN "$TestFilePath\$TestFileName" Start-Sleep -Seconds 5 -Verbose $iops = $Result.Split("`n")[10].Split(':')[1].Trim() $mbs = $Result.Split("`n")[11].Split(':')[1].Trim() $latency = $Result.Split("`n")[14].Split(':')[1].Trim() $SeqRnd = $Result.Split("`n")[14].Split(':')[1].Trim() New-object psobject -property @{ Type = $($Type) SizeIOKBytes = $($KBytes) OutStandingIOs = $($_) IOPS = $($iops) MBSec = $($mbs) LatencyMS = $($latency) Target = $("$TestFilePath\$TestFileName") } } } #Checking for fast mode if ($FastMode -lt $True){$Duration = '-s60'}else{$Duration = '-s10'} #Setting script location to find the exe's $RunningFromFolder = $MyInvocation.MyCommand.Path | Split-Path -Parent Write-Host “Running this from $RunningFromFolder” #Main . New-TestFile switch ($OutputFormat){ 'Out-GridView' { . $TestMode | Select-Object MBSec,IOPS,SizeIOKBytes,LatencyMS,OutStandingIOs,Type,Target | Out-GridView } 'Format-Table' { . $TestMode | Select-Object MBSec,IOPS,SizeIOKBytes,LatencyMS,OutStandingIOs,Type,Target | Format-Table } Default {} } . Remove-TestFile |
good
What’s up to all, since I am really eager of reading this website’s post to be updated
daily. It includes good information.
Have you ever thought about including a ittle bit more
than just your articles? I mean, wwhat you say is fundamental and
everything. But think about if you added some great visuals or
video clipps to give your posts more, “pop”!
Your content is excellent but with images and clips, this blog could undeniably bee one of the greatest in its field.
Awesome blog!
You should be a part of a contest for one of the best
sites on the web. I’m going to recommend this web
site!
If you wish for to improve your know-how just keep visiting this site and be updated with the most
up-to-date information posted here.
Hello, yeah this post is in fact good and I have learned lot of things from it
regarding blogging. thanks.