diff --git a/tests/benchmarks/SharpCoreDB.Benchmarks.Comparative/Program.cs b/tests/benchmarks/SharpCoreDB.Benchmarks.Comparative/Program.cs index c3614872..041cafe5 100644 --- a/tests/benchmarks/SharpCoreDB.Benchmarks.Comparative/Program.cs +++ b/tests/benchmarks/SharpCoreDB.Benchmarks.Comparative/Program.cs @@ -954,6 +954,39 @@ data TEXT return result; } + /// + /// D1: runs a fair-PK arm several times and reports the per-phase median time so the printed + /// ops/s is robust to run-to-run noise (single-shot arms fluctuated by roughly ±30%). + /// + private static BenchmarkResult RunPkMedian(Func arm, int reps = 3) + { + var runs = new List(reps); + for (int r = 0; r < reps; r++) + { + runs.Add(arm()); + } + + static double MedianOf(IEnumerable xs, Func select) + { + var sorted = xs.Select(select).Where(x => x > 0).OrderBy(x => x).ToArray(); + return sorted.Length == 0 ? 0 : sorted[sorted.Length / 2]; + } + + var median = new BenchmarkResult + { + InsertTime = MedianOf(runs, static r => r.InsertTime), + ReadTime = MedianOf(runs, static r => r.ReadTime), + UpdateTime = MedianOf(runs, static r => r.UpdateTime), + DeleteTime = MedianOf(runs, static r => r.DeleteTime), + }; + + median.InsertOpsPerSec = InsertCount > 0 && median.InsertTime > 0 ? (int)(InsertCount / median.InsertTime) : 0; + median.ReadOpsPerSec = ReadCount > 0 && median.ReadTime > 0 ? (int)(ReadCount / median.ReadTime) : 0; + median.UpdateOpsPerSec = UpdateCount > 0 && median.UpdateTime > 0 ? (int)(UpdateCount / median.UpdateTime) : 0; + median.DeleteOpsPerSec = DeleteCount > 0 && median.DeleteTime > 0 ? (int)(DeleteCount / median.DeleteTime) : 0; + return median; + } + /// /// Runs the fair PK scenario (SharpCoreDB vs SQLite) and prints the comparison. /// @@ -966,17 +999,18 @@ static void RunPkComparison(SharpCoreDB.Interfaces.StorageEngineType engineType) Console.WriteLine("╚══════════════════════════════════════════════════════════╝"); Console.WriteLine(); Console.WriteLine($"Engine: {engineLabel}"); + Console.WriteLine("(fair-PK arms run 3x; median time per phase is reported)"); Console.WriteLine("━━━ SharpCoreDB (SQL, PK, legacy variable-length) ━━━"); - var scdb = RunSharpCoreDBPk(engineType); + var scdb = RunPkMedian(() => RunSharpCoreDBPk(engineType)); Console.WriteLine(); Console.WriteLine("━━━ SharpCoreDB (SQL, PK, fixed-width) ━━━"); - var scdbFw = RunSharpCoreDBPk(engineType, fixedWidth: true); + var scdbFw = RunPkMedian(() => RunSharpCoreDBPk(engineType, fixedWidth: true)); Console.WriteLine(); Console.WriteLine("━━━ SQLite (reference) ━━━"); - var sqlite = RunSQLite(); + var sqlite = RunPkMedian(() => RunSQLite()); Console.WriteLine(); Console.WriteLine("║ Database │ INSERT │ READ │ UPDATE │ DELETE ║");