Skip to content

Instantly share code, notes, and snippets.

@jhochwald
Created January 26, 2023 19:31
Show Gist options
  • Save jhochwald/55e1b4454232b0435ebec05d5f2d0d58 to your computer and use it in GitHub Desktop.
Save jhochwald/55e1b4454232b0435ebec05d5f2d0d58 to your computer and use it in GitHub Desktop.
File I/O Speed-Testing - compare native .NET vs. native Powershell (Just an example)
#requires -Version 3.0
<#
.SYNOPSIS
File I/O Speed-Testing
.DESCRIPTION
File I/O Speed-Testing
.PARAMETER ReadFile
File to Read (must exist)
.PARAMETER WriteTarget
File to Write
.PARAMETER Number
Number of times, the inputfile is multiplied (to simmulate more, bigger, I/O)
.PARAMETER InputFile
File to read for the test (MUST EXIST)
.PARAMETER TestRun
Time to run the test
Default is:2
Min: 1
Max: 5
.EXAMPLE
PS C:\> .\FileSpeedTest.ps1
.NOTES
Basic example for some I/O tests
We decided to use a smaller input-file and multiply the content to generate a bigger one. In our test-case, the input-file hat about 500KB.
You can use a bigger one, and decrease the multiplication (-Number).
You can also increase the number of tests (-TestRun), but then you should reduce the output or save it into a log (can get long)
#>
[CmdletBinding(ConfirmImpact = 'None')]
[OutputType([string])]
param
(
[Parameter(ValueFromPipeline,
ValueFromPipelineByPropertyName)]
[ValidateNotNullOrEmpty()]
[string]
$ReadFile = 'c:\temp\test_large.txt',
[Parameter(ValueFromPipeline,
ValueFromPipelineByPropertyName)]
[ValidateNotNullOrEmpty()]
[string]
$WriteTarget = 'c:\temp\test.txt',
[Parameter(ValueFromPipeline,
ValueFromPipelineByPropertyName)]
[ValidateNotNullOrEmpty()]
[int]
$Number = 100,
[Parameter(ValueFromPipeline,
ValueFromPipelineByPropertyName)]
[ValidateNotNullOrEmpty()]
[string]
$InputFile = 'C:\DEV\Temp\Product names and service plan identifiers for licensing_raw.csv',
[Parameter(ValueFromPipeline,
ValueFromPipelineByPropertyName)]
[ValidateRange(1, 5)]
[ValidateNotNullOrEmpty()]
[int]
$TestRun = 2
)
begin
{
Clear-Host
Write-Verbose -Message ('Prepare file ({0} time the input)' -f $Number)
#region GenerateTestData
$DNETDATA = ([IO.File]::ReadAllLines($InputFile))
$WriteData = (1 .. $Number | ForEach-Object -Process {
$DNETDATA
})
$null = ([IO.file]::WriteAllText($ReadFile, $WriteData))
#endregion GenerateTestData
#region Functions
function Format-FileSize
{
[CmdletBinding(ConfirmImpact = 'None')]
[OutputType([string])]
param
(
[Parameter(Mandatory, HelpMessage = 'File-Size to tranform/format',
ValueFromPipeline,
ValueFromPipelineByPropertyName)]
[ValidateNotNullOrEmpty()]
[int]
$size
)
process
{
switch ($size)
{
{
$_ -gt 1TB
}
{
[string]::Format('{0:0.00} TB', $size / 1TB)
}
{
$_ -gt 1GB
}
{
[string]::Format('{0:0.00} GB', $size / 1GB)
}
{
$_ -gt 1MB
}
{
[string]::Format('{0:0.00} MB', $size / 1MB)
}
{
$_ -gt 1KB
}
{
[string]::Format('{0:0.00} kB', $size / 1KB)
}
{
$_ -gt 0
}
{
[string]::Format('{0:0.00} B', $size)
}
Default
{
'Unknown size'
break
}
}
}
}
#endregion Functions
('The Test-File size is: {0}' -f $(Format-FileSize -size ((Get-Item -Path $ReadFile).length)))
' '
$DNETDATA = $null
'---------------------------------------------------------------------------------'
#region ScriptBlock
$ScriptBlock = {
' '
('-> READCOUNT: {0}' -f $_)
' '
'Read - PowerShell:'
([int](Measure-Command -Expression {
$null = (Get-Content -Path $ReadFile)
}).TotalMilliseconds)
' '
'Read - .NET System.IO (ReadAllLines):'
([int](Measure-Command -Expression {
$null = ([IO.File]::ReadAllLines($ReadFile))
}).TotalMilliseconds)
' '
'Read - .NET System.IO (ReadAllText):'
([int](Measure-Command -Expression {
$null = ([IO.File]::ReadAllText($ReadFile))
}).TotalMilliseconds)
' '
('-> WRITECOUNT: {0}' -f $_)
$null = (Remove-Item -Path $WriteTarget -Force -ErrorAction SilentlyContinue)
' '
'Write - PowerShell (Set-Content):'
([int](Measure-Command -Expression {
$null = ($WriteData | Set-Content -Path $WriteTarget -Force)
}).TotalMilliseconds)
$null = (Remove-Item -Path $WriteTarget -Force -ErrorAction SilentlyContinue)
' '
'Write - PowerShell (Out-File):'
([int](Measure-Command -Expression {
$null = ($WriteData | Out-File -FilePath $WriteTarget -Force)
}).TotalMilliseconds)
$null = (Remove-Item -Path $WriteTarget -Force -ErrorAction SilentlyContinue)
' '
'Read - .NET System.IO (WriteAllText):'
([int](Measure-Command -Expression {
$null = ([IO.file]::WriteAllText($WriteTarget, $WriteData))
}).TotalMilliseconds)
$null = (Remove-Item -Path $WriteTarget -Force -ErrorAction SilentlyContinue)
' '
'Read - .NET System.IO (AppendAllText):'
([int](Measure-Command -Expression {
$null = ([IO.file]::AppendAllText($WriteTarget, $WriteData))
}).TotalMilliseconds)
$null = (Remove-Item -Path $WriteTarget -Force -ErrorAction SilentlyContinue)
' '
'---------------------------------------------------------------------------------'
}
#endregion ScriptBlock
}
process
{
1 .. $TestRun | ForEach-Object -Process {
(Invoke-Command -ScriptBlock $ScriptBlock)
}
}
@jhochwald
Copy link
Author

This is just an example! You need to use a valid input (text) file. You can multiply the input and run the tests as often as you like. Re-Run (e.g., run it multiple times) can prevent any warmup or caching events.
Do not run (-TestRun) the tests within one loop. You need to scroll (a lot) to gather all the information. On the other hand, you can pipe everything into a log!

The file is just a showcase, nothing more nothing less!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment