Improve benchmark project
Add reference tests
Add script to run locally easily
Add script to read results quickly
Add script to write results to SQL database
This commit is contained in:
Luc Genetier 2023-01-06 17:49:50 +01:00 коммит произвёл GitHub
Родитель 075c0d1395
Коммит e0e5c5427c
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
9 изменённых файлов: 651 добавлений и 12 удалений

314
.scripts/WriteBenchmark.ps1 Normal file
Просмотреть файл

@ -0,0 +1,314 @@
param(
[Parameter (Mandatory = $true)] [String]$ConnectionString
)
## $env:BUILD_SOURCESDIRECTORY = "C:\Data\2\Power-Fx"
## $env:BUILD_DEFINITIONNAME = "Test"
## $env:BUILD_BUILDID = "69992023"
## $env:BUILD_BUILDNUMBER = "2023.X1"
## $env:BUILDCONFIGURATION = "TestRelease"
function ConvertToMs([string]$str)
{
try
{
if (($str.Trim() -eq '-') -or [string]::IsNullOrEmpty($str.Trim()))
{
$val = [double]0
}
else
{
$parts = $str.Split(@(' '), [System.StringSplitOptions]::RemoveEmptyEntries)
$val = [double]$parts[0]
## Convert to milliseconds
if ($parts[1] -eq "s") { $val *= 1000 }
elseif ($parts[1] -eq "ms") { } ## Do nothing
elseif ($parts[1] -eq "µs") { $val /= 1000 }
elseif ($parts[1] -eq "ns") { $val /= 1000000 }
else { throw ("Unknown unit: " + $parts[1]) }
}
$val
}
catch
{
Write-Error $_
}
}
function ConvertToBytes([string]$str)
{
try
{
$parts = $str.Split(@(' '), [System.StringSplitOptions]::RemoveEmptyEntries)
$val = [double]$parts[0]
## Convert to milliseconds
if ($parts[1] -eq "B") { } ## Do nothing
elseif ($parts[1] -eq "kB") { $val *= 1024 }
elseif ($parts[1] -eq "MB") { $val *= 1048576 }
elseif ($parts[1] -eq "GB") { $val *= 1073741824 }
else { throw ("Unknown unit: " + $parts[1]) }
$val
}
catch
{
Write-Error $_
}
}
## Retrieve Power Fx latest Git hash and Git remote branch
cd ($env:BUILD_SOURCESDIRECTORY)
$pfxHash = (git log -n 1 --pretty=%H).ToString()
$pfxBranch = (git log -n 1 --pretty=%D).Split(", /")
$pfxBranch = $pfxBranch[$pfxBranch.Length-1]
Write-Host "------ Git context ------"
Write-Host "PFX Hash : $pfxHash"
Write-Host "PFX Branch: $pfxBranch"
Write-Host
cd src
if (-not (Test-Path "BenchmarkDotNet.Artifacts"))
{
Write-Host -ForegroundColor Yellow "No BenchmarkDotNet.Artifacts folder!"
Write-Host -ForegroundColor DarkYellow "Run benchmark first."
dir
exit
}
Write-Host "------ Test context ------"
$cpuFile = "BenchmarkDotNet.Artifacts\cpu.csv"
$memoryFile = "BenchmarkDotNet.Artifacts\memory.csv"
$referenceFile = "BenchmarkDotNet.Artifacts\results\Microsoft.PowerFx.Performance.Tests.Reference-report-github.md"
## Read CPU file, fixed size columns
$index = 0; $x = 0
foreach ($line in (Get-Content $cpuFile))
{
## Get headers and identify their positon
if ($index -eq 0)
{
$headers = $line.Split(@(' '), [System.StringSplitOptions]::RemoveEmptyEntries)
$hdrs = [System.Collections.ArrayList]::new()
$l = $line
for ($i = 0; $i -lt $headers.Length; $i++)
{
$y = $line.IndexOf($headers[$i])
$x += $y
[void]$hdrs.Add($x)
$line = $line.Substring($headers[$i].Length + $y )
$x += $headers[$i].Length
}
[void]$hdrs.Add($x)
}
if ($index -eq 1)
{
$cpuModel = $line.Substring($hdrs[0], $hdrs[1] - $hdrs[0]).Trim()
$cpuSpeed = [int]::Parse($line.Substring($hdrs[1], $hdrs[2] - $hdrs[1]).Trim())
$cpuName = $line.Substring($hdrs[2], $hdrs[3] - $hdrs[2]).Trim()
$numberCores = [int]::Parse($line.Substring($hdrs[3], $hdrs[4] - $hdrs[3]).Trim())
$numberLogicalProcs = [int]::Parse($line.Substring($hdrs[4], $hdrs[5] - $hdrs[4]).Trim())
}
$index++
}
Write-Host "CPU Model : $cpuModel"
Write-Host "CPU Speed (MHz) : $cpuSpeed"
Write-Host "CPU Name : $cpuName"
Write-Host "Number Cores : $numberCores"
Write-Host "Logical processors: $numberLogicalProcs"
## Read CPU file, fixed size columns
$index = 0; $x = 0; $memory = [double]0;
foreach ($line in (Get-Content $memoryFile))
{
## Get headers and identify their positon
if ($index -eq 0)
{
$headers = $line.Split(@(' '), [System.StringSplitOptions]::RemoveEmptyEntries)
$hdrs = [System.Collections.ArrayList]::new()
$l = $line
for ($i = 0; $i -lt $headers.Length; $i++)
{
$y = $line.IndexOf($headers[$i])
$x += $y
[void]$hdrs.Add($x)
$line = $line.Substring($headers[$i].Length + $y )
$x += $headers[$i].Length
}
[void]$hdrs.Add($x)
}
if ($index -eq 1)
{
$memory = [double]::Parse($line.Substring($hdrs[0], $hdrs[1] - $hdrs[0]).Trim());
}
$index++
}
$memoryGB = $memory / [double]1024 / [double]1024 / [double]1024;
Write-Host "Memory (GB) : $memoryGB"
$index = 0
foreach ($line in (Get-Content $referenceFile))
{
if ($index -in @(2, 4))
{
foreach ($a in ($line.Split(@(','), [System.StringSplitOptions]::RemoveEmptyEntries) | % { $_.Trim() }))
{
$b = $a.Split(@('='), [System.StringSplitOptions]::RemoveEmptyEntries) | % { $_.Trim() }
if ($b[0] -eq 'BenchmarkDotNet') { $bmdnVersion = $b[1] }
if ($b[0] -eq 'OS') { $osVersion = $b[1] }
if ($b[0] -eq 'VM') { $vmType = $b[1] }
if ($b[0] -in @('.Net Core SDK', '.NET SDK')) { $dnRTVersion = $b[1] }
}
}
if ($index -eq 6)
{
$a = $line.Split(@(':'), [System.StringSplitOptions]::RemoveEmptyEntries) | % { $_.Trim() }
$dnVersion = $a[1]
}
$index++
}
Write-Host "BenchmarkDotNet : $bmdnVersion"
Write-Host "OS Version : $osVersion"
Write-Host "VM Type : $vmType"
Write-Host ".Net RT Version : $dnRTVersion"
Write-Host ".Net Version : $dnVersion"
Write-Host
$Connection = New-Object System.Data.SQLClient.SQLConnection
$Connection.ConnectionString = $ConnectionString
$Connection.Open()
$Command = New-Object System.Data.SQLClient.SQLCommand
$Command.Connection = $Connection
$insertQuery = "insert into Runs ([TimeStamp], [Hash], [Pipeline], [BuildId], [BuildNumber], [BuildConfiguration], [Branch]) "
$insertQuery += "values (getutcdate(), '$pfxHash', '$env:BUILD_DEFINITIONNAME', '$env:BUILD_BUILDID', '$env:BUILD_BUILDNUMBER', '$env:BUILDCONFIGURATION', '$pfxBranch');"
$insertQuery += "select scope_identity() as 'Id'"
$Command.CommandText = $insertquery
$runId = $Command.ExecuteScalar()
Write-Host "RunId: $runId"
$insertQuery = "insert into Contexts ([RunId], [CPUModel], [CPUSpeedMHz], [CPUName], [NumberCores], [LogicalProcessors], [MemoryGB], [BenchMarkDotNetVersion], [OS], [VM], [DotNetRuntime], [DotNetVersion]) "
$insertQuery += "values ('$runId', '$cpuModel', '$cpuSpeed', '$cpuName', '$numberCores', '$numberLogicalProcs', '$memoryGB', '$bmdnVersion', '$osVersion', '$vmType', '$dnRTVersion', '$dnVersion');"
$insertQuery += "select scope_identity() as 'Id'"
$Command.CommandText = $insertquery
$contextId = $Command.ExecuteScalar()
Write-Host "ContextId: $contextId"
Write-Host
## Always start the list of results with the Reference CSV file
$list = (Get-Item -Filter *.csv -Path '.\BenchmarkDotNet.Artifacts\results\*' | % { $_.FullName })
foreach ($file in [System.Linq.Enumerable]::OrderBy($list, [Func[object, string]] { param($s) if ($s -match 'Reference-report\.csv') { "" } else { $s } }))
{
$t = [System.IO.Path]::GetFileNameWithoutExtension($file).Split(@('.'))[-1]
$testCategory = $t.Substring(0, $t.Length - 7)
Write-Host "------ [TEST] $testCategory ------"
$table = [System.Data.DataTable]::new()
[void]$table.Columns.Add("TestName", [string]); $table.Columns["TestName"].AllowDBNull = $false
[void]$table.Columns.Add("N", [int]); $table.Columns["N"].AllowDBNull = $true ## Optional column, depends on the test
[void]$table.Columns.Add("Mean", [double]); $table.Columns["Mean"].AllowDBNull = $false
[void]$table.Columns.Add("StdDev", [double]); $table.Columns["StdDev"].AllowDBNull = $false
[void]$table.Columns.Add("Min", [double]); $table.Columns["Min"].AllowDBNull = $false
[void]$table.Columns.Add("Q1", [double]); $table.Columns["Q1"].AllowDBNull = $false
[void]$table.Columns.Add("Median", [double]); $table.Columns["Median"].AllowDBNull = $false
[void]$table.Columns.Add("Q3", [double]); $table.Columns["Q3"].AllowDBNull = $false
[void]$table.Columns.Add("Max", [double]); $table.Columns["Max"].AllowDBNull = $false
[void]$table.Columns.Add("Gen0", [double]); $table.Columns["Gen0"].AllowDBNull = $false
[void]$table.Columns.Add("Gen1", [double]); $table.Columns["Gen1"].AllowDBNull = $false
[void]$table.Columns.Add("Allocated", [double]); $table.Columns["Allocated"].AllowDBNull = $false
[void]$table.Columns.Add("AllocatedNativeMemory", [double]); $table.Columns["AllocatedNativeMemory"].AllowDBNull = $false
[void]$table.Columns.Add("NativeMemoryLeak", [double]); $table.Columns["NativeMemoryLeak"].AllowDBNull = $false
foreach ($row in (Import-Csv $file | Select-Object Method, Runtime, N, Mean, StdDev, Min, Q1, Median, Q3, Max, Gen0, Gen1, Allocated, 'Allocated Native Memory', 'Native Memory Leak'))
{
$mean = ConvertToMs($row.Mean)
$stddev = ConvertToMs($row.StdDev)
$min = ConvertToMs($row.Min)
$q1 = ConvertToMs($row.Q1)
$median = ConvertToMs($row.Median)
$q3 = ConvertToMs($row.Q3)
$max = ConvertToMs($row.Max)
$gen0 = $row.Gen0 ## Gen X means number of GC collections per 1000 operations for that generation
$gen1 = $row.Gen1
$alloc = ConvertToBytes($row.Allocated)
$native = ConvertToBytes($row.'Allocated Native Memory')
$leak = ConvertToBytes($row.'Native Memory Leak')
if (($gen0 -eq $null) -or ($gen0.Trim() -eq '-') -or [string]::IsNullOrEmpty($gen0.Trim())) { $gen0 = [double]0 }
if (($gen1 -eq $null) -or ($gen1.Trim() -eq '-') -or [string]::IsNullOrEmpty($gen1.Trim())) { $gen1 = [double]0 }
[void]$table.Rows.Add($row.Method, $row.N, $mean, $stddev, $min, $q1, $median, $q3, $max, $gen0, $gen1, $alloc, $native, $leak)
}
$table | Sort-Object TestName, N | ft TestName, N, Mean, StdDev, Min, Q1, Median, Q3, Max, Gen0, Gen1, Allocated, AllocatedNativeMemory, NativeMemoryLeak
$ctxids = [System.Collections.ArrayList]::new()
foreach ($row in $table)
{
$testName = $row.TestName
$n = $row.N
$mean = $row.Mean
$stdDev = $row.StdDev
$min = $row.Min
$q1 = $row.Q1
$median = $row.Median
$q3 = $row.Q3
$max = $row.Max
$gen0 = $row.Gen0
$gen1 = $row.Gen1
$alloc = $row.Allocated
$native = $row.AllocatedNativeMemory
$leak = $row.NativeMemoryLeak
$insertQuery = "insert into Tests ([RunId], [ContextId], [TestName], [N], [MeanMs], [StdDevMs], [MinMs], [Q1Ms], [MedianMs], [Q3Ms], [MaxMs], [Gen0], [Gen1], [Allocated], [AllocatedNativeMemory], [NativeMemoryLeak]) "
$insertQuery += "values ('$runId', '$contextId', '$testName', "
if ($n.GetType() -eq [DBNull])
{
$insertQuery += "null"
}
else
{
$insertQuery += "'$n'"
}
$insertQuery += ", '$mean', '$stdDev', '$min', '$q1', '$median', '$q3', '$max', '$gen0', '$gen1', '$alloc', '$native', '$leak'); "
$insertQuery += "select scope_identity() as 'Id'"
$Command.CommandText = $insertquery
$id = $Command.ExecuteScalar()
[void]$ctxids.Add($id)
}
Write-Host "TestIds: " ([String]::Join(', ', $ctxids.ToArray()))
Write-Host
}
Write-Host "--- End of script ---"

Просмотреть файл

@ -73,7 +73,7 @@
<Copyright>© Microsoft Corporation. All rights reserved.</Copyright>
</PropertyGroup>
<PropertyGroup Condition="'$(Project)'!='Microsoft.PowerFx.Performance.Tests'">
<PropertyGroup Condition=" '$(ProjectName)' != 'Microsoft.PowerFx.Performance.Tests' ">
<AssemblyOriginatorKeyFile Condition="EXISTS('..\..\..\src\build\35MSSharedLib1024.snk')">..\..\..\src\build\35MSSharedLib1024.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly>
<DelaySign>true</DelaySign>

Просмотреть файл

@ -44,7 +44,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerFx.Performan
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{5EEC2873-35B5-4364-A2A0-97AAD7BF960D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Repl", "tools\Repl\Repl.csproj", "{142854D7-409C-4C87-A5B8-39B51477F5B2}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Repl", "tools\Repl\Repl.csproj", "{142854D7-409C-4C87-A5B8-39B51477F5B2}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Benchmark", "Benchmark", "{4167C30B-F9D2-4187-87DA-85864AD2AA94}"
ProjectSection(SolutionItems) = preProject
ReadBenchmarkData.ps1 = ReadBenchmarkData.ps1
RunBenchmark.cmd = RunBenchmark.cmd
..\.scripts\WriteBenchmark.ps1 = ..\.scripts\WriteBenchmark.ps1
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerFx.Json", "libraries\Microsoft.PowerFx.Json\Microsoft.PowerFx.Json.csproj", "{D4CC6660-8C30-41E5-A28A-C018DDDF8D96}"
EndProject

220
src/ReadBenchmarkData.ps1 Normal file
Просмотреть файл

@ -0,0 +1,220 @@
if (-not (Test-Path "BenchmarkDotNet.Artifacts"))
{
Write-Host -ForegroundColor Yellow "No BenchmarkDotNet.Artifacts folder!"
Write-Host -ForegroundColor DarkYellow "Run benchmark first."
exit
}
function ConvertToMs([string]$str)
{
try
{
if (($str.Trim() -eq '-') -or [string]::IsNullOrEmpty($str.Trim()))
{
$val = [double]0
}
else
{
$parts = $str.Split(@(' '), [System.StringSplitOptions]::RemoveEmptyEntries)
$val = [double]$parts[0]
## Convert to milliseconds
if ($parts[1] -eq "s") { $val *= 1000 }
elseif ($parts[1] -eq "ms") { } ## Do nothing
elseif ($parts[1] -eq "µs") { $val /= 1000 }
elseif ($parts[1] -eq "ns") { $val /= 1000000 }
else { throw ("Unknown unit: " + $parts[1]) }
}
$val
}
catch
{
Write-Error $_
}
}
function ConvertToBytes([string]$str)
{
try
{
$parts = $str.Split(@(' '), [System.StringSplitOptions]::RemoveEmptyEntries)
$val = [double]$parts[0]
## Convert to milliseconds
if ($parts[1] -eq "B") { } ## Do nothing
elseif ($parts[1] -eq "kB") { $val *= 1024 }
elseif ($parts[1] -eq "MB") { $val *= 1048576 }
elseif ($parts[1] -eq "GB") { $val *= 1073741824 }
else { throw ("Unknown unit: " + $parts[1]) }
$val
}
catch
{
Write-Error $_
}
}
Write-Host "------ Test context ------"
$cpuFile = "BenchmarkDotNet.Artifacts\cpu.csv"
$memoryFile = "BenchmarkDotNet.Artifacts\memory.csv"
$referenceFile = "BenchmarkDotNet.Artifacts\results\Microsoft.PowerFx.Performance.Tests.Reference-report-github.md"
## Read CPU file, fixed size columns
$index = 0; $x = 0
foreach ($line in (Get-Content $cpuFile))
{
## Get headers and identify their positon
if ($index -eq 0)
{
$headers = $line.Split(@(' '), [System.StringSplitOptions]::RemoveEmptyEntries)
$hdrs = [System.Collections.ArrayList]::new()
$l = $line
for ($i = 0; $i -lt $headers.Length; $i++)
{
$y = $line.IndexOf($headers[$i])
$x += $y
[void]$hdrs.Add($x)
$line = $line.Substring($headers[$i].Length + $y )
$x += $headers[$i].Length
}
[void]$hdrs.Add($x)
}
if ($index -eq 1)
{
$cpuModel = $line.Substring($hdrs[0], $hdrs[1] - $hdrs[0]).Trim()
$cpuSpeed = [int]::Parse($line.Substring($hdrs[1], $hdrs[2] - $hdrs[1]).Trim())
$cpuName = $line.Substring($hdrs[2], $hdrs[3] - $hdrs[2]).Trim()
$numberCores = [int]::Parse($line.Substring($hdrs[3], $hdrs[4] - $hdrs[3]).Trim())
$numberLogicalProcs = [int]::Parse($line.Substring($hdrs[4], $hdrs[5] - $hdrs[4]).Trim())
}
$index++
}
Write-Host "CPU Model : $cpuModel"
Write-Host "CPU Speed (MHz) : $cpuSpeed"
Write-Host "CPU Name : $cpuName"
Write-Host "Number Cores : $numberCores"
Write-Host "Logical processors: $numberLogicalProcs"
## Read CPU file, fixed size columns
$index = 0; $x = 0; $memory = [double]0;
foreach ($line in (Get-Content $memoryFile))
{
## Get headers and identify their positon
if ($index -eq 0)
{
$headers = $line.Split(@(' '), [System.StringSplitOptions]::RemoveEmptyEntries)
$hdrs = [System.Collections.ArrayList]::new()
$l = $line
for ($i = 0; $i -lt $headers.Length; $i++)
{
$y = $line.IndexOf($headers[$i])
$x += $y
[void]$hdrs.Add($x)
$line = $line.Substring($headers[$i].Length + $y )
$x += $headers[$i].Length
}
[void]$hdrs.Add($x)
}
if ($index -eq 1)
{
$memory = [double]::Parse($line.Substring($hdrs[0], $hdrs[1] - $hdrs[0]).Trim());
}
$index++
}
$memoryGB = $memory / [double]1024 / [double]1024 / [double]1024;
Write-Host "Memory (GB) : $memoryGB"
$index = 0
foreach ($line in (Get-Content $referenceFile))
{
if ($index -in @(2, 4))
{
foreach ($a in ($line.Split(@(','), [System.StringSplitOptions]::RemoveEmptyEntries) | % { $_.Trim() }))
{
$b = $a.Split(@('='), [System.StringSplitOptions]::RemoveEmptyEntries) | % { $_.Trim() }
if ($b[0] -eq 'BenchmarkDotNet') { $bmdnVersion = $b[1] }
if ($b[0] -eq 'OS') { $osVersion = $b[1] }
if ($b[0] -eq 'VM') { $vmType = $b[1] }
if ($b[0] -in @('.Net Core SDK', '.NET SDK')) { $dnRTVersion = $b[1] }
}
}
if ($index -eq 6)
{
$a = $line.Split(@(':'), [System.StringSplitOptions]::RemoveEmptyEntries) | % { $_.Trim() }
$dnVersion = $a[1]
}
$index++
}
Write-Host "BenchmarkDotNet : $bmdnVersion"
Write-Host "OS Version : $osVersion"
Write-Host "VM Type : $vmType"
Write-Host ".Net RT Version : $dnRTVersion"
Write-Host ".Net Version : $dnVersion"
Write-Host
## Always start the list of results with the Reference CSV file
$list = (Get-Item -Filter *.csv -Path '.\BenchmarkDotNet.Artifacts\results\*' | % { $_.FullName })
foreach ($file in [System.Linq.Enumerable]::OrderBy($list, [Func[object, string]] { param($s) if ($s -match 'Reference-report\.csv') { "" } else { $s } }))
{
$t = [System.IO.Path]::GetFileNameWithoutExtension($file).Split(@('.'))[-1]
$testCategory = $t.Substring(0, $t.Length - 7)
Write-Host "------ [TEST] $testCategory ------"
$table = [System.Data.DataTable]::new()
[void]$table.Columns.Add("TestName", [string]); $table.Columns["TestName"].AllowDBNull = $false
[void]$table.Columns.Add("N", [int]); $table.Columns["N"].AllowDBNull = $true ## Optional column, depends on the test
[void]$table.Columns.Add("Mean", [double]); $table.Columns["Mean"].AllowDBNull = $false
[void]$table.Columns.Add("StdDev", [double]); $table.Columns["StdDev"].AllowDBNull = $false
[void]$table.Columns.Add("Min", [double]); $table.Columns["Min"].AllowDBNull = $false
[void]$table.Columns.Add("Q1", [double]); $table.Columns["Q1"].AllowDBNull = $false
[void]$table.Columns.Add("Median", [double]); $table.Columns["Median"].AllowDBNull = $false
[void]$table.Columns.Add("Q3", [double]); $table.Columns["Q3"].AllowDBNull = $false
[void]$table.Columns.Add("Max", [double]); $table.Columns["Max"].AllowDBNull = $false
[void]$table.Columns.Add("Gen0", [double]); $table.Columns["Gen0"].AllowDBNull = $false
[void]$table.Columns.Add("Gen1", [double]); $table.Columns["Gen1"].AllowDBNull = $false
[void]$table.Columns.Add("Allocated", [double]); $table.Columns["Allocated"].AllowDBNull = $false
[void]$table.Columns.Add("AllocatedNativeMemory", [double]); $table.Columns["AllocatedNativeMemory"].AllowDBNull = $false
[void]$table.Columns.Add("NativeMemoryLeak", [double]); $table.Columns["NativeMemoryLeak"].AllowDBNull = $false
foreach ($row in (Import-Csv $file | Select-Object Method, Runtime, N, Mean, StdDev, Min, Q1, Median, Q3, Max, Gen0, Gen1, Allocated, 'Allocated Native Memory', 'Native Memory Leak'))
{
$mean = ConvertToMs($row.Mean)
$stddev = ConvertToMs($row.StdDev)
$min = ConvertToMs($row.Min)
$q1 = ConvertToMs($row.Q1)
$median = ConvertToMs($row.Median)
$q3 = ConvertToMs($row.Q3)
$max = ConvertToMs($row.Max)
$gen0 = $row.Gen0 ## Gen X means number of GC collections per 1000 operations for that generation
$gen1 = $row.Gen1
$alloc = ConvertToBytes($row.Allocated)
$native = ConvertToBytes($row.'Allocated Native Memory')
$leak = ConvertToBytes($row.'Native Memory Leak')
if (($gen0 -eq $null) -or ($gen0.Trim() -eq '-') -or [string]::IsNullOrEmpty($gen0.Trim())) { $gen0 = [double]0 }
if (($gen1 -eq $null) -or ($gen1.Trim() -eq '-') -or [string]::IsNullOrEmpty($gen1.Trim())) { $gen1 = [double]0 }
[void]$table.Rows.Add($row.Method, $row.N, $mean, $stddev, $min, $q1, $median, $q3, $max, $gen0, $gen1, $alloc, $native, $leak)
}
$table | Sort-Object TestName, N | ft TestName, N, Mean, StdDev, Min, Q1, Median, Q3, Max, Gen0, Gen1, Allocated, AllocatedNativeMemory, NativeMemoryLeak
Write-Host
}
Write-Host '--- End of script ---'

10
src/runBenchmark.cmd Normal file
Просмотреть файл

@ -0,0 +1,10 @@
@echo off
if not exist "BenchmarkDotNet.Artifacts" md "BenchmarkDotNet.Artifacts"
wmic cpu get Caption, CurrentClockSpeed, Name, NumberOfCores, NumberOfLogicalProcessors > BenchmarkDotNet.Artifacts\cpu.csv
wmic computersystem get TotalPhysicalMemory > BenchmarkDotNet.Artifacts\memory.csv
for /f %%a in ('dotnet --list-sdks ^| findstr 3\.1') do set dotnetver=%%a
set MSBuildSDKsPath=C:\Program Files\dotnet\sdk\%dotnetver%\sdks
if not exist global.json dotnet new globaljson --sdk-version %dotnetver%
"tests\Microsoft.PowerFx.Performance.Tests\bin\Release\netcoreapp3.1\Microsoft.PowerFx.Performance.Tests.exe" --list tree
"tests\Microsoft.PowerFx.Performance.Tests\bin\Release\netcoreapp3.1\Microsoft.PowerFx.Performance.Tests.exe" -f *
del global.json

Просмотреть файл

@ -7,19 +7,24 @@ using System.Linq;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Diagnostics.Windows;
using BenchmarkDotNet.Diagnostics.Windows.Configs;
using BenchmarkDotNet.Jobs;
using Microsoft.PowerFx.Syntax;
using Microsoft.PowerFx.Types;
namespace Microsoft.PowerFx.Performance.Tests
{
[MemoryDiagnoser]
[NativeMemoryProfiler]
[EtwProfiler] // https://benchmarkdotnet.org/articles/features/etwprofiler.html
[CsvExporter] // https://benchmarkdotnet.org/articles/configs/exporters.html
[MinColumn]
[Q1Column]
[MeanColumn]
[MedianColumn]
[Q3Column]
[MaxColumn]
public class PerformanceTest1
[SimpleJob(runtimeMoniker: RuntimeMoniker.NetCoreApp31)]
public class BasicPerformance
{
private PowerFxConfig _powerFxConfig;
private Engine _engine;

Просмотреть файл

@ -8,7 +8,9 @@
<GenerateDocumentationFile>false</GenerateDocumentationFile>
<StartupObject>Microsoft.PowerFx.Performance.Tests.Program</StartupObject>
<LangVersion>9.0</LangVersion>
<AssemblyName>Microsoft.PowerFx.Performance.Benchmarks</AssemblyName>
<AssemblyName>Microsoft.PowerFx.Performance.Tests</AssemblyName>
<SignAssembly>False</SignAssembly>
<DelaySign>False</DelaySign>
</PropertyGroup>
<ItemGroup>

Просмотреть файл

@ -9,16 +9,30 @@ namespace Microsoft.PowerFx.Performance.Tests
{
public static void Main(string[] args)
{
/*
*
* --> This program needs to be run ELEVATED
*
* --> Also set the following env. variable before starting VS
* SET MSBuildSDKsPath=C:\Program Files\dotnet\sdk\7.0.100\Sdks
*
/*
1. Build in Release mode
2. Then, execute the following commands (from cmd.exe, ELEVATED [required for ETW generation])
set MSBuildSDKsPath=C:\Program Files\dotnet\sdk\3.1.426\sdks
cd <repo root>\src
dotnet new globaljson --sdk-version 3.1.426
"tests\Microsoft.PowerFx.Performance.Tests\bin\Release\netcoreapp3.1\Microsoft.PowerFx.Performance.Tests.exe" -f *
Notice that version 3.1.426 or other versions are obtained with "dotnet --list-sdks"
"dotnet new globaljson --sdk-version 3.1.426" shouldn't be needed
Results are in
- <repo root>\src\BenchmarkDotNet.Artifacts
Microsoft.PowerFx.Performance.Tests.<test class>-<date>-<time>.log
Microsoft.PowerFx.Performance.Tests.<test class and name (+opt. N)>-<date>-<time>.etl
- <repo root>\src\BenchmarkDotNet.Artifacts\results
Microsoft.PowerFx.Performance.Tests.<test class>-report-github.md
Microsoft.PowerFx.Performance.Tests.<test class>-report.html
Microsoft.PowerFx.Performance.Tests.<test class>-report.csv
*/
var summary = BenchmarkRunner.Run<PerformanceTest1>();
_ = BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args);
}
}
}

Просмотреть файл

@ -0,0 +1,67 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Diagnostics.Windows.Configs;
using BenchmarkDotNet.Engines;
using BenchmarkDotNet.Jobs;
using Microsoft.PowerFx.Syntax;
namespace Microsoft.PowerFx.Performance.Tests
{
[MemoryDiagnoser]
[NativeMemoryProfiler]
[EtwProfiler] // https://benchmarkdotnet.org/articles/features/etwprofiler.html
[CsvExporter] // https://benchmarkdotnet.org/articles/configs/exporters.html
[MinColumn]
[Q1Column]
[MeanColumn]
[MedianColumn]
[Q3Column]
[MaxColumn]
[SimpleJob(runtimeMoniker: RuntimeMoniker.NetCoreApp31)]
// The objective of this set of tests is to serve as a reference in order to
// compare results between them if the server on which they are run have
// different performances
// - FixedDuration is supposed to take 100ms, always
// - FixedLoop will always have a fixed set of instructions and its duration
// should only depend on the CPU speed
public class Reference
{
[GlobalSetup]
public void GlobalSetup()
{
CultureInfo.CurrentCulture = new CultureInfo("en-US");
}
[Benchmark]
[MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
public int FixedDuration()
{
// Fixed duration, independant of CPU speed
Thread.Sleep(100);
return 0;
}
[Benchmark]
[MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
public long FixedLoop()
{
var j = 0;
for (var i = 0; i < 10000000; i++)
{
j += i;
}
return j;
}
}
}