summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/LivingVillage.Desktop.Tests/LivingVillage.Desktop.Tests.fsproj1
-rw-r--r--src/LivingVillage.Desktop.Tests/PerformanceSummaryTests.fs34
-rw-r--r--src/LivingVillage.Desktop/LivingVillage.Desktop.fsproj1
-rw-r--r--src/LivingVillage.Desktop/PerformanceSummary.fs27
4 files changed, 63 insertions, 0 deletions
diff --git a/src/LivingVillage.Desktop.Tests/LivingVillage.Desktop.Tests.fsproj b/src/LivingVillage.Desktop.Tests/LivingVillage.Desktop.Tests.fsproj
index 87e9e9d..a0c98b0 100644
--- a/src/LivingVillage.Desktop.Tests/LivingVillage.Desktop.Tests.fsproj
+++ b/src/LivingVillage.Desktop.Tests/LivingVillage.Desktop.Tests.fsproj
@@ -12,6 +12,7 @@
<Compile Include="P16UiTests.fs" />
<Compile Include="PrototypeTests.fs" />
<Compile Include="MapGenTests.fs" />
+ <Compile Include="PerformanceSummaryTests.fs" />
<Compile Include="M3BatchOutputTests.fs" />
<Compile Include="SampleTests.fs" />
</ItemGroup>
diff --git a/src/LivingVillage.Desktop.Tests/PerformanceSummaryTests.fs b/src/LivingVillage.Desktop.Tests/PerformanceSummaryTests.fs
new file mode 100644
index 0000000..cd7c3b1
--- /dev/null
+++ b/src/LivingVillage.Desktop.Tests/PerformanceSummaryTests.fs
@@ -0,0 +1,34 @@
+namespace LivingVillage.Desktop.Tests
+
+open System
+open Microsoft.VisualStudio.TestTools.UnitTesting
+open LivingVillage.Desktop
+
+[<TestClass>]
+type PerformanceSummaryTests () =
+
+ let close (expected: float) (actual: float) =
+ Assert.IsTrue(abs (expected - actual) < 0.0001, sprintf "expected %f but got %f" expected actual)
+
+ [<TestMethod>]
+ member _.SummarizeDropsWarmupAndReportsMeanMinMax () =
+ match PerformanceSummary.summarize 2 [ 10.0; 20.0; 30.0; 40.0 ] with
+ | None -> Assert.Fail("expected a summary")
+ | Some summary ->
+ Assert.AreEqual<int>(2, summary.Count)
+ close 35.0 summary.Mean
+ close 30.0 summary.Min
+ close 40.0 summary.Max
+
+ [<TestMethod>]
+ member _.SummarizeReturnsNoneWhenNoRealSampleRemains () =
+ Assert.IsTrue((PerformanceSummary.summarize 5 [ 1.0; 2.0 ]).IsNone)
+ Assert.IsTrue((PerformanceSummary.summarize 0 []).IsNone)
+
+ [<TestMethod>]
+ member _.SummarizeWithZeroWarmupKeepsEverySample () =
+ match PerformanceSummary.summarize 0 [ 60.0; 59.5; 61.0 ] with
+ | None -> Assert.Fail("expected a summary")
+ | Some summary ->
+ Assert.AreEqual<int>(3, summary.Count)
+ close 59.5 summary.Min
diff --git a/src/LivingVillage.Desktop/LivingVillage.Desktop.fsproj b/src/LivingVillage.Desktop/LivingVillage.Desktop.fsproj
index 6f388f2..2901dce 100644
--- a/src/LivingVillage.Desktop/LivingVillage.Desktop.fsproj
+++ b/src/LivingVillage.Desktop/LivingVillage.Desktop.fsproj
@@ -19,6 +19,7 @@
<Compile Include="SampleScript.fs" />
<Compile Include="M6Presentation.fs" />
<Compile Include="HudLayout.fs" />
+ <Compile Include="PerformanceSummary.fs" />
<Compile Include="TitleScreen.fs" />
<Compile Include="Game.fs" />
diff --git a/src/LivingVillage.Desktop/PerformanceSummary.fs b/src/LivingVillage.Desktop/PerformanceSummary.fs
new file mode 100644
index 0000000..3edb4a7
--- /dev/null
+++ b/src/LivingVillage.Desktop/PerformanceSummary.fs
@@ -0,0 +1,27 @@
+namespace LivingVillage.Desktop
+
+/// P21:纯函数的帧率采样汇总(均值/最低/最高),供实机性能核对与回归测试。
+/// 不含时钟/IO,只看传入的每秒 FPS 样本序列;warmup 采样用于剔除启动抖动。
+module PerformanceSummary =
+
+ type Summary =
+ { Count: int
+ Mean: float
+ Min: float
+ Max: float }
+
+ /// 丢弃前 `warmupSamples` 个样本(不足则全丢),对剩余样本求均值/最低/最高。
+ /// 剩余为空时返回 None(如运行过短)。
+ let summarize (warmupSamples: int) (samples: float list) : Summary option =
+ let skip = max 0 warmupSamples
+ let taken =
+ if List.length samples <= skip then []
+ else samples |> List.skip skip
+ match taken with
+ | [] -> None
+ | _ ->
+ Some
+ { Count = taken.Length
+ Mean = List.average taken
+ Min = List.min taken
+ Max = List.max taken }