From 6f904d6f8528bd13941894af3db16d0bc3b0aeb3 Mon Sep 17 00:00:00 2001 From: "Somhairle H. Marisol" Date: Sun, 20 Sep 2026 19:32:52 +0800 Subject: perf: add simulation baseline probe --- .../LivingVillage.Kernel.Tests.fsproj | 2 + src/LivingVillage.Kernel.Tests/PerformanceTests.fs | 51 ++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 src/LivingVillage.Kernel.Tests/PerformanceTests.fs (limited to 'src/LivingVillage.Kernel.Tests') diff --git a/src/LivingVillage.Kernel.Tests/LivingVillage.Kernel.Tests.fsproj b/src/LivingVillage.Kernel.Tests/LivingVillage.Kernel.Tests.fsproj index b30fc8f..f618dc9 100644 --- a/src/LivingVillage.Kernel.Tests/LivingVillage.Kernel.Tests.fsproj +++ b/src/LivingVillage.Kernel.Tests/LivingVillage.Kernel.Tests.fsproj @@ -12,6 +12,7 @@ + @@ -22,6 +23,7 @@ + diff --git a/src/LivingVillage.Kernel.Tests/PerformanceTests.fs b/src/LivingVillage.Kernel.Tests/PerformanceTests.fs new file mode 100644 index 0000000..c7e65e4 --- /dev/null +++ b/src/LivingVillage.Kernel.Tests/PerformanceTests.fs @@ -0,0 +1,51 @@ +namespace LivingVillage.Kernel.Tests + +open System +open System.Diagnostics +open Microsoft.VisualStudio.TestTools.UnitTesting +open LivingVillage.Headless + +[] +type PerformanceTests () = + + let testConfiguration = + { PerformanceProbe.defaultConfiguration with + WarmupTicks = 32 + MeasureTicks = 256 + Repetitions = 1 } + + [] + member _.FixedSeedAndInputSequenceProduceTheSameWorldDigest () = + let first = PerformanceProbe.runSteps testConfiguration + let second = PerformanceProbe.runSteps testConfiguration + + Assert.AreEqual( + int64 (testConfiguration.WarmupTicks + testConfiguration.MeasureTicks), + first.Tick) + Assert.AreEqual(testConfiguration.NpcCount, first.Npcs.Length) + Assert.AreEqual(PerformanceProbe.worldDigest first, PerformanceProbe.worldDigest second) + + [] + member _.MeasurementReportsConfiguredTicksAndRuntimeCounters () = + let sample = PerformanceProbe.measure testConfiguration + + Assert.AreEqual(testConfiguration.MeasureTicks, sample.MeasureTicks) + Assert.AreEqual(int64 (testConfiguration.WarmupTicks + testConfiguration.MeasureTicks), sample.FinalTick) + Assert.AreEqual(Stopwatch.Frequency, sample.StopwatchFrequency) + Assert.IsTrue(sample.ElapsedStopwatchTicks > 0L) + Assert.IsTrue(sample.AllocatedBytes >= 0L) + Assert.IsTrue(sample.Gen0Collections >= 0L) + Assert.IsTrue(sample.Gen1Collections >= 0L) + Assert.IsTrue(sample.Gen2Collections >= 0L) + let formatted = PerformanceProbe.formatSample sample + Assert.IsTrue(formatted.Contains("ticks_per_second=")) + Assert.IsTrue(formatted.Contains("allocated_bytes=")) + Assert.IsTrue(formatted.Contains("gen0=")) + + [] + member _.InvalidConfigurationReportsAUsefulFailure () = + let invalid = { testConfiguration with NpcCount = 0 } + + match PerformanceProbe.validateConfiguration invalid with + | Ok () -> Assert.Fail("zero NPC configuration must be rejected") + | Error message -> Assert.IsTrue(message.Contains("NpcCount")) -- cgit v1.2.3