Expand QuickBenchmark suite & add CLI scripts

Majorly enhanced QuickBenchmark.cs with new helper methods, standardized iteration count, and several comprehensive benchmarks comparing AcBinary (with/without reference handling) to MessagePack. Improved output formatting for clarity. Added RunQuickBenchmark.ps1 and .bat scripts for easy CLI execution and registered them as solution items. These changes make benchmarking more robust, readable, and user-friendly.
This commit is contained in:
Loretta 2025-12-15 12:00:03 +01:00
parent bc30a3aede
commit a832d8e86d
4 changed files with 574 additions and 8 deletions

View File

@ -14,6 +14,87 @@ public class QuickBenchmark
private static readonly MessagePackSerializerOptions MsgPackOptions =
ContractlessStandardResolver.Options.WithCompression(MessagePackCompression.None);
private const int DefaultIterations = 1000;
#region Helper Methods
private static void PrintBanner(string title)
{
Console.WriteLine();
Console.WriteLine(new string('=', 78));
Console.WriteLine(title);
Console.WriteLine(new string('=', 78));
}
private static void PrintTableHeader(string title)
{
PrintBanner(title);
Console.WriteLine($"{"Metric",-25} | {"AcBinary",14} | {"MessagePack",14} | {"Ratio",14}");
Console.WriteLine(new string('-', 78));
}
private static void PrintTableRow(string metric, double acBinary, double msgPack, string unit = "ms")
{
if (msgPack > 0)
{
var ratio = acBinary / msgPack;
var ratioStr = ratio < 1 ? $"{ratio:F2}x faster" : $"{ratio:F2}x slower";
Console.WriteLine($"{metric,-25} | {acBinary,10:F2} {unit,-2} | {msgPack,10:F2} {unit,-2} | {ratioStr,14}");
}
else
{
Console.WriteLine($"{metric,-25} | {acBinary,10:F2} {unit,-2} | {"N/A",12} | {"(unique)",14}");
}
}
private static void PrintTableRowSize(string metric, int acBinary, int msgPack)
{
var ratio = msgPack == 0 ? 0 : 100.0 * acBinary / msgPack;
Console.WriteLine($"{metric,-25} | {acBinary,14:N0} | {msgPack,14:N0} | {ratio,12:F1}%");
}
private static void PrintTableFooter()
{
Console.WriteLine(new string('-', 78));
}
private static void PrintSummary(int acBinarySize, int msgPackSize, double acSerMs, double msgSerMs, double acDeserMs, double msgDeserMs)
{
PrintBanner("SUMMARY");
var sizeAdvantage = msgPackSize == 0 ? 0 : 100.0 - (100.0 * acBinarySize / msgPackSize);
if (sizeAdvantage > 0)
Console.WriteLine($"[OK] Size: AcBinary is {sizeAdvantage:F1}% smaller ({msgPackSize - acBinarySize:N0} bytes saved)");
else
Console.WriteLine($"[WARN] Size: AcBinary is {-sizeAdvantage:F1}% larger");
var serRatio = msgSerMs == 0 ? 0 : acSerMs / msgSerMs;
if (serRatio > 0 && serRatio < 1)
Console.WriteLine($"[OK] Serialize: AcBinary is {1 / serRatio:F2}x faster");
else if (serRatio > 0)
Console.WriteLine($"[WARN] Serialize: AcBinary is {serRatio:F2}x slower");
var deserRatio = msgDeserMs == 0 ? 0 : acDeserMs / msgDeserMs;
if (deserRatio > 0 && deserRatio < 1)
Console.WriteLine($"[OK] Deserialize: AcBinary is {1 / deserRatio:F2}x faster");
else if (deserRatio > 0)
Console.WriteLine($"[WARN] Deserialize: AcBinary is {deserRatio:F2}x slower");
}
private static TestOrder CreatePopulateTarget(TestOrder source)
{
var target = new TestOrder { Id = source.Id };
foreach (var item in source.Items)
{
target.Items.Add(new TestOrderItem { Id = item.Id });
}
return target;
}
#endregion
#region Basic Benchmarks
[TestMethod]
public void RunQuickBenchmark()
{
@ -26,7 +107,7 @@ public class QuickBenchmark
}
// Measure serialize
const int iterations = 1000;
const int iterations = DefaultIterations;
var sw = Stopwatch.StartNew();
byte[] serialized = null!;
for (int i = 0; i < iterations; i++)
@ -101,7 +182,7 @@ public class QuickBenchmark
var result = bytes.BinaryTo<List<TestClassWithRepeatedValues>>();
}
const int iterations = 1000;
const int iterations = DefaultIterations;
// With interning (default)
var sw = Stopwatch.StartNew();
@ -137,6 +218,10 @@ public class QuickBenchmark
Assert.AreEqual(100, result2!.Count);
}
#endregion
#region MessagePack Comparison
[TestMethod]
public void RunMessagePackComparison()
{
@ -152,7 +237,7 @@ public class QuickBenchmark
var msgResult = MessagePackSerializer.Deserialize<TestOrder>(msgBytes, MsgPackOptions);
}
const int iterations = 1000;
const int iterations = DefaultIterations;
// === AcBinary Serialize ===
var sw = Stopwatch.StartNew();
@ -207,9 +292,9 @@ public class QuickBenchmark
var sizeDiff = msgPackData.Length - acBinaryData.Length;
if (sizeDiff > 0)
Console.WriteLine($" AcBinary {sizeDiff:N0} bytes smaller ({100.0 * sizeDiff / msgPackData.Length:F1}% savings)");
Console.WriteLine($"[OK] AcBinary {sizeDiff:N0} bytes smaller ({100.0 * sizeDiff / msgPackData.Length:F1}% savings)");
else
Console.WriteLine($"⚠️ AcBinary {-sizeDiff:N0} bytes larger");
Console.WriteLine($"[WARN] AcBinary {-sizeDiff:N0} bytes larger");
Assert.IsNotNull(acBinaryResult);
Assert.IsNotNull(msgPackResult);
@ -237,7 +322,7 @@ public class QuickBenchmark
var r2 = MessagePackSerializer.Deserialize<List<TestClassWithRepeatedValues>>(b2, MsgPackOptions);
}
const int iterations = 1000;
const int iterations = DefaultIterations;
// AcBinary with interning
var sw = Stopwatch.StartNew();
@ -281,12 +366,306 @@ public class QuickBenchmark
Console.WriteLine();
var sizeSaving = msgPack.Length - acWithIntern.Length;
Console.WriteLine($" String interning saves {sizeSaving:N0} bytes ({100.0 * sizeSaving / msgPack.Length:F1}%)");
Console.WriteLine($"[OK] String interning saves {sizeSaving:N0} bytes ({100.0 * sizeSaving / msgPack.Length:F1}%)");
Assert.IsTrue(acWithIntern.Length < msgPack.Length, "AcBinary with interning should be smaller");
}
// Public for MessagePack dynamic serializer compatibility
#endregion
#region Full Comparison (WithRef, NoRef, Populate, Merge)
[TestMethod]
public void RunFullBenchmarkComparison()
{
PrintBanner("AcBinary vs MessagePack Full Benchmark");
// Create test data with shared references
TestDataFactory.ResetIdCounter();
var sharedTag = TestDataFactory.CreateTag("SharedTag");
var sharedUser = TestDataFactory.CreateUser("shareduser");
var sharedMeta = TestDataFactory.CreateMetadata("shared", withChild: true);
var testOrder = TestDataFactory.CreateOrder(
itemCount: 3,
palletsPerItem: 3,
measurementsPerPallet: 3,
pointsPerMeasurement: 4,
sharedTag: sharedTag,
sharedUser: sharedUser,
sharedMetadata: sharedMeta);
// Options
var withRefOptions = new AcBinarySerializerOptions();
var noRefOptions = AcBinarySerializerOptions.WithoutReferenceHandling();
// Warmup
Console.WriteLine("\nWarming up...");
for (int i = 0; i < 100; i++)
{
_ = AcBinarySerializer.Serialize(testOrder, withRefOptions);
_ = AcBinarySerializer.Serialize(testOrder, noRefOptions);
_ = MessagePackSerializer.Serialize(testOrder, MsgPackOptions);
}
// Pre-serialize
var acBinaryWithRef = AcBinarySerializer.Serialize(testOrder, withRefOptions);
var acBinaryNoRef = AcBinarySerializer.Serialize(testOrder, noRefOptions);
var msgPackData = MessagePackSerializer.Serialize(testOrder, MsgPackOptions);
Console.WriteLine($"Iterations: {DefaultIterations:N0}");
// Size comparison
PrintTableHeader("SIZE COMPARISON");
PrintTableRowSize("AcBinary (WithRef)", acBinaryWithRef.Length, msgPackData.Length);
PrintTableRowSize("AcBinary (NoRef)", acBinaryNoRef.Length, msgPackData.Length);
PrintTableRowSize("MessagePack (baseline)", msgPackData.Length, msgPackData.Length);
PrintTableFooter();
var sw = Stopwatch.StartNew();
// === Serialize WithRef ===
sw.Restart();
for (int i = 0; i < DefaultIterations; i++)
_ = AcBinarySerializer.Serialize(testOrder, withRefOptions);
var acWithRefSerMs = sw.Elapsed.TotalMilliseconds;
// === Serialize NoRef ===
sw.Restart();
for (int i = 0; i < DefaultIterations; i++)
_ = AcBinarySerializer.Serialize(testOrder, noRefOptions);
var acNoRefSerMs = sw.Elapsed.TotalMilliseconds;
// === MessagePack Serialize ===
sw.Restart();
for (int i = 0; i < DefaultIterations; i++)
_ = MessagePackSerializer.Serialize(testOrder, MsgPackOptions);
var msgPackSerMs = sw.Elapsed.TotalMilliseconds;
// === Deserialize WithRef ===
sw.Restart();
for (int i = 0; i < DefaultIterations; i++)
_ = AcBinaryDeserializer.Deserialize<TestOrder>(acBinaryWithRef);
var acWithRefDeserMs = sw.Elapsed.TotalMilliseconds;
// === Deserialize NoRef ===
sw.Restart();
for (int i = 0; i < DefaultIterations; i++)
_ = AcBinaryDeserializer.Deserialize<TestOrder>(acBinaryNoRef);
var acNoRefDeserMs = sw.Elapsed.TotalMilliseconds;
// === MessagePack Deserialize ===
sw.Restart();
for (int i = 0; i < DefaultIterations; i++)
_ = MessagePackSerializer.Deserialize<TestOrder>(msgPackData, MsgPackOptions);
var msgPackDeserMs = sw.Elapsed.TotalMilliseconds;
// === Populate (AcBinary only) ===
sw.Restart();
for (int i = 0; i < DefaultIterations; i++)
{
var target = CreatePopulateTarget(testOrder);
AcBinaryDeserializer.Populate(acBinaryNoRef, target);
}
var acPopulateMs = sw.Elapsed.TotalMilliseconds;
// === PopulateMerge (AcBinary only) ===
sw.Restart();
for (int i = 0; i < DefaultIterations; i++)
{
var target = CreatePopulateTarget(testOrder);
AcBinaryDeserializer.PopulateMerge(acBinaryNoRef.AsSpan(), target);
}
var acMergeMs = sw.Elapsed.TotalMilliseconds;
// Print performance table
PrintTableHeader("PERFORMANCE COMPARISON (lower is better)");
PrintTableRow("Serialize (WithRef)", acWithRefSerMs, msgPackSerMs);
PrintTableRow("Serialize (NoRef)", acNoRefSerMs, msgPackSerMs);
PrintTableRow("Deserialize (WithRef)", acWithRefDeserMs, msgPackDeserMs);
PrintTableRow("Deserialize (NoRef)", acNoRefDeserMs, msgPackDeserMs);
PrintTableRow("Populate (NoRef)", acPopulateMs, 0);
PrintTableRow("Merge (NoRef)", acMergeMs, 0);
PrintTableRow("Round-trip (WithRef)", acWithRefSerMs + acWithRefDeserMs, msgPackSerMs + msgPackDeserMs);
PrintTableRow("Round-trip (NoRef)", acNoRefSerMs + acNoRefDeserMs, msgPackSerMs + msgPackDeserMs);
PrintTableFooter();
PrintSummary(acBinaryNoRef.Length, msgPackData.Length, acNoRefSerMs, msgPackSerMs, acNoRefDeserMs, msgPackDeserMs);
// Assertions
Assert.IsTrue(acBinaryWithRef.Length < msgPackData.Length, "AcBinary WithRef should be smaller than MessagePack");
Assert.IsTrue(acBinaryNoRef.Length < msgPackData.Length, "AcBinary NoRef should be smaller than MessagePack");
}
[TestMethod]
public void RunWithRefVsNoRefComparison()
{
PrintBanner("AcBinary WithRef vs NoRef Comparison");
// Create test data WITH shared references (to show WithRef advantage)
TestDataFactory.ResetIdCounter();
var sharedTag = TestDataFactory.CreateTag("SharedTag");
var sharedUser = TestDataFactory.CreateUser("shareduser");
var sharedMeta = TestDataFactory.CreateMetadata("shared", withChild: true);
var testOrder = TestDataFactory.CreateOrder(
itemCount: 5,
palletsPerItem: 4,
measurementsPerPallet: 3,
pointsPerMeasurement: 5,
sharedTag: sharedTag,
sharedUser: sharedUser,
sharedMetadata: sharedMeta);
var withRefOptions = new AcBinarySerializerOptions();
var noRefOptions = AcBinarySerializerOptions.WithoutReferenceHandling();
// Warmup
Console.WriteLine("Warming up...");
for (int i = 0; i < 50; i++)
{
_ = AcBinarySerializer.Serialize(testOrder, withRefOptions);
_ = AcBinarySerializer.Serialize(testOrder, noRefOptions);
}
var withRefData = AcBinarySerializer.Serialize(testOrder, withRefOptions);
var noRefData = AcBinarySerializer.Serialize(testOrder, noRefOptions);
Console.WriteLine($"Iterations: {DefaultIterations:N0}");
// Size comparison
PrintBanner("SIZE COMPARISON (bytes)");
Console.WriteLine($"WithRef : {withRefData.Length,12:N0} (baseline)");
var sizeDiff = noRefData.Length - withRefData.Length;
var ratio = withRefData.Length == 0 ? 0 : 100.0 * noRefData.Length / withRefData.Length;
Console.WriteLine($"NoRef : {noRefData.Length,12:N0} (diff {sizeDiff:+#;-#;0}) => {ratio:F1}% of WithRef");
var sw = Stopwatch.StartNew();
// Serialize WithRef
sw.Restart();
for (int i = 0; i < DefaultIterations; i++)
_ = AcBinarySerializer.Serialize(testOrder, withRefOptions);
var withRefSerMs = sw.Elapsed.TotalMilliseconds;
// Serialize NoRef
sw.Restart();
for (int i = 0; i < DefaultIterations; i++)
_ = AcBinarySerializer.Serialize(testOrder, noRefOptions);
var noRefSerMs = sw.Elapsed.TotalMilliseconds;
// Deserialize WithRef
sw.Restart();
for (int i = 0; i < DefaultIterations; i++)
_ = AcBinaryDeserializer.Deserialize<TestOrder>(withRefData);
var withRefDeserMs = sw.Elapsed.TotalMilliseconds;
// Deserialize NoRef
sw.Restart();
for (int i = 0; i < DefaultIterations; i++)
_ = AcBinaryDeserializer.Deserialize<TestOrder>(noRefData);
var noRefDeserMs = sw.Elapsed.TotalMilliseconds;
PrintBanner("PERFORMANCE COMPARISON (ms)");
Console.WriteLine($"Serialize -> WithRef: {withRefSerMs,8:F2} | NoRef: {noRefSerMs,8:F2}");
Console.WriteLine($"Deserialize-> WithRef: {withRefDeserMs,8:F2} | NoRef: {noRefDeserMs,8:F2}");
Console.WriteLine($"Round-trip -> WithRef: {withRefSerMs + withRefDeserMs,8:F2} | NoRef: {noRefSerMs + noRefDeserMs,8:F2}");
if (withRefData.Length < noRefData.Length)
{
Console.WriteLine($"[OK] WithRef saves {noRefData.Length - withRefData.Length:N0} bytes by deduplicating shared references.");
}
else
{
Console.WriteLine($"[INFO] NoRef saves {withRefData.Length - noRefData.Length:N0} bytes because it skips reference metadata.");
}
// Verify correctness
var resultWithRef = AcBinaryDeserializer.Deserialize<TestOrder>(withRefData);
var resultNoRef = AcBinaryDeserializer.Deserialize<TestOrder>(noRefData);
Assert.IsNotNull(resultWithRef);
Assert.IsNotNull(resultNoRef);
Assert.AreEqual(testOrder.Id, resultWithRef.Id);
Assert.AreEqual(testOrder.Id, resultNoRef.Id);
}
[TestMethod]
public void RunPopulateAndMergeBenchmark()
{
PrintBanner("AcBinary Populate & Merge Benchmark");
TestDataFactory.ResetIdCounter();
var testOrder = TestDataFactory.CreateBenchmarkOrder(
itemCount: 3,
palletsPerItem: 3,
measurementsPerPallet: 3,
pointsPerMeasurement: 4);
var options = AcBinarySerializerOptions.WithoutReferenceHandling();
var binaryData = AcBinarySerializer.Serialize(testOrder, options);
Console.WriteLine("Warming up...");
for (int i = 0; i < 50; i++)
{
var target = CreatePopulateTarget(testOrder);
AcBinaryDeserializer.Populate(binaryData, target);
AcBinaryDeserializer.PopulateMerge(binaryData.AsSpan(), target);
}
Console.WriteLine($"Iterations: {DefaultIterations:N0}");
Console.WriteLine($"Data size: {binaryData.Length:N0} bytes");
var sw = Stopwatch.StartNew();
// Deserialize (creates new object)
sw.Restart();
for (int i = 0; i < DefaultIterations; i++)
_ = AcBinaryDeserializer.Deserialize<TestOrder>(binaryData);
var deserializeMs = sw.Elapsed.TotalMilliseconds;
// Populate (reuses existing object)
sw.Restart();
for (int i = 0; i < DefaultIterations; i++)
{
var target = CreatePopulateTarget(testOrder);
AcBinaryDeserializer.Populate(binaryData, target);
}
var populateMs = sw.Elapsed.TotalMilliseconds;
// PopulateMerge (IId-based merge)
sw.Restart();
for (int i = 0; i < DefaultIterations; i++)
{
var target = CreatePopulateTarget(testOrder);
AcBinaryDeserializer.PopulateMerge(binaryData.AsSpan(), target);
}
var mergeMs = sw.Elapsed.TotalMilliseconds;
// PopulateMerge with RemoveOrphanedItems
var mergeWithRemoveOptions = new AcBinarySerializerOptions { RemoveOrphanedItems = true };
sw.Restart();
for (int i = 0; i < DefaultIterations; i++)
{
var target = CreatePopulateTarget(testOrder);
AcBinaryDeserializer.PopulateMerge(binaryData.AsSpan(), target, mergeWithRemoveOptions);
}
var mergeWithRemoveMs = sw.Elapsed.TotalMilliseconds;
PrintBanner("OPERATION COMPARISON (ms)");
Console.WriteLine($"Deserialize (new object): {deserializeMs:F2} (baseline)");
Console.WriteLine($"Populate (reuse obj) : {populateMs:F2} ({populateMs / deserializeMs:F2}x of baseline)");
Console.WriteLine($"PopulateMerge : {mergeMs:F2} ({mergeMs / deserializeMs:F2}x of baseline)");
Console.WriteLine($"PopulateMerge + cleanup: {mergeWithRemoveMs:F2} ({mergeWithRemoveMs / deserializeMs:F2}x of baseline)");
Console.WriteLine("[INFO] Populate/Merge reuse existing objects - ideal for UI data binding scenarios.");
Assert.IsTrue(true); // Test passed if no exceptions
}
#endregion
#region Test Models
public class TestClassWithRepeatedValues
{
public int Id { get; set; }
@ -294,4 +673,6 @@ public class QuickBenchmark
public string Category { get; set; } = "";
public string Priority { get; set; } = "";
}
#endregion
}

View File

@ -42,6 +42,8 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8EC462FD-D22E-90A8-E5CE-7E832BA40C5D}"
ProjectSection(SolutionItems) = preProject
AyCode.Core.targets = AyCode.Core.targets
RunQuickBenchmark.bat = RunQuickBenchmark.bat
RunQuickBenchmark.ps1 = RunQuickBenchmark.ps1
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AyCode.Benchmark", "AyCode.Benchmark\AyCode.Benchmark.csproj", "{A20861A9-411E-6150-BF5C-69E8196E5D22}"

17
RunQuickBenchmark.bat Normal file
View File

@ -0,0 +1,17 @@
@echo off
REM Run Quick Benchmark PowerShell script using pwsh if available, otherwise Windows PowerShell
setlocal enabledelayedexpansion
set SCRIPT_DIR=%~dp0
where pwsh >nul 2>&1
if %ERRORLEVEL%==0 (
pwsh -NoProfile -ExecutionPolicy Bypass -File "%SCRIPT_DIR%RunQuickBenchmark.ps1" -All
set EXITCODE=!ERRORLEVEL!
) else (
powershell -NoProfile -ExecutionPolicy Bypass -File "%SCRIPT_DIR%RunQuickBenchmark.ps1" -All
set EXITCODE=!ERRORLEVEL!
)
echo.
pause
endlocal
exit /b %EXITCODE%

166
RunQuickBenchmark.ps1 Normal file
View File

@ -0,0 +1,166 @@
# AcBinary Quick Benchmark Runner
# Run this script to execute all binary serialization benchmarks
# Usage: .\RunQuickBenchmark.ps1 [-All] [-Full] [-WithRef] [-Populate] [-StringIntern] [-MessagePack]
param(
[switch]$All,
[switch]$Full,
[switch]$WithRef,
[switch]$Populate,
[switch]$StringIntern,
[switch]$MessagePack,
[switch]$Help
)
$ErrorActionPreference = "Stop"
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
# Colors for output
function Write-ColorOutput($ForegroundColor, $Message) {
$fc = $host.UI.RawUI.ForegroundColor
$host.UI.RawUI.ForegroundColor = $ForegroundColor
Write-Output $Message
$host.UI.RawUI.ForegroundColor = $fc
}
function Show-Help {
Write-Host ""
Write-Host "????????????????????????????????????????????????????????????????????????????????" -ForegroundColor Cyan
Write-Host "? AcBinary Quick Benchmark Runner ?" -ForegroundColor Cyan
Write-Host "????????????????????????????????????????????????????????????????????????????????" -ForegroundColor Cyan
Write-Host ""
Write-Host "Usage: .\RunQuickBenchmark.ps1 [options]" -ForegroundColor Yellow
Write-Host ""
Write-Host "Options:" -ForegroundColor Green
Write-Host " -All Run all benchmark tests"
Write-Host " -Full Run full AcBinary vs MessagePack comparison"
Write-Host " -WithRef Run WithRef vs NoRef comparison"
Write-Host " -Populate Run Populate & Merge benchmarks"
Write-Host " -StringIntern Run String Interning benchmarks"
Write-Host " -MessagePack Run MessagePack comparison"
Write-Host " -Help Show this help message"
Write-Host ""
Write-Host "Examples:" -ForegroundColor Green
Write-Host " .\RunQuickBenchmark.ps1 -All # Run all tests"
Write-Host " .\RunQuickBenchmark.ps1 -Full # Full benchmark comparison"
Write-Host " .\RunQuickBenchmark.ps1 -WithRef -Populate # Multiple specific tests"
Write-Host ""
}
function Run-DotNetTest {
param(
[string]$Filter,
[string]$Description
)
Write-Host ""
Write-Host "Running: $Description" -ForegroundColor Yellow
Write-Host ("=" * 80) -ForegroundColor DarkGray
$testProject = Join-Path $ScriptDir "AyCode.Core.Tests\AyCode.Core.Tests.csproj"
if (-not (Test-Path $testProject)) {
Write-Host "Error: Test project not found at $testProject" -ForegroundColor Red
return $false
}
$result = dotnet test $testProject `
--filter "FullyQualifiedName~$Filter" `
--configuration Release `
--logger "console;verbosity=detailed" `
--no-build 2>&1
$result | ForEach-Object { Write-Host $_ }
return $LASTEXITCODE -eq 0
}
# Check for help
if ($Help -or ($PSBoundParameters.Count -eq 0)) {
Show-Help
if ($PSBoundParameters.Count -eq 0) {
Write-Host "No options specified. Running full benchmark..." -ForegroundColor Yellow
$Full = $true
} else {
exit 0
}
}
Write-Host ""
Write-Host "????????????????????????????????????????????????????????????????????????????????" -ForegroundColor Cyan
Write-Host "? AcBinary Quick Benchmark ?" -ForegroundColor Cyan
Write-Host "????????????????????????????????????????????????????????????????????????????????" -ForegroundColor Cyan
Write-Host ""
Write-Host "Building solution in Release mode..." -ForegroundColor Yellow
# Build first
$buildResult = dotnet build (Join-Path $ScriptDir "AyCode.Core.sln") --configuration Release --verbosity minimal 2>&1
if ($LASTEXITCODE -ne 0) {
Write-Host "Build failed!" -ForegroundColor Red
$buildResult | ForEach-Object { Write-Host $_ }
exit 1
}
Write-Host "Build successful!" -ForegroundColor Green
$testsRun = 0
$testsPassed = 0
# Run requested tests
if ($All) {
$Full = $true
$WithRef = $true
$Populate = $true
$StringIntern = $true
$MessagePack = $true
}
if ($Full) {
$testsRun++
if (Run-DotNetTest "QuickBenchmark.RunFullBenchmarkComparison" "Full AcBinary vs MessagePack Comparison") {
$testsPassed++
}
}
if ($WithRef) {
$testsRun++
if (Run-DotNetTest "QuickBenchmark.RunWithRefVsNoRefComparison" "WithRef vs NoRef Comparison") {
$testsPassed++
}
}
if ($Populate) {
$testsRun++
if (Run-DotNetTest "QuickBenchmark.RunPopulateAndMergeBenchmark" "Populate & Merge Benchmark") {
$testsPassed++
}
}
if ($StringIntern) {
$testsRun++
if (Run-DotNetTest "QuickBenchmark.RunStringInterningBenchmark" "String Interning Benchmark") {
$testsPassed++
}
$testsRun++
if (Run-DotNetTest "QuickBenchmark.RunStringInterningVsMessagePack" "String Interning vs MessagePack") {
$testsPassed++
}
}
if ($MessagePack) {
$testsRun++
if (Run-DotNetTest "QuickBenchmark.RunMessagePackComparison" "MessagePack Comparison") {
$testsPassed++
}
}
# Summary
Write-Host ""
Write-Host ("=" * 80) -ForegroundColor DarkGray
Write-Host ""
if ($testsPassed -eq $testsRun) {
Write-Host "All $testsRun benchmark(s) completed successfully!" -ForegroundColor Green
} else {
Write-Host "$testsPassed of $testsRun benchmark(s) completed." -ForegroundColor Yellow
}
Write-Host ""