summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorSomhairle H. Marisol <[email protected]>2026-09-29 09:42:17 +0800
committerSomhairle H. Marisol <[email protected]>2026-09-29 09:42:17 +0800
commitf01aa1a9a8d19db5ab908ddbb30b0467be8aa092 (patch)
tree2385fd0b75b3b35f5a29ac9b5c02d9b9e5aea13b /docs
parent54732d906a68d89ee1446ddb82ae639a016925be (diff)
downloadliving-village-f01aa1a9a8d19db5ab908ddbb30b0467be8aa092.tar.gz
p70: 启动帧率与渲染基准(真实可复跑数据)
- scripts/bench-p70.sh:两档基准——Kernel --performance-baseline(6000 tick ×3) + Desktop xvfb 60s 真实帧循环;scripts/analyze-p70.py 汇总裁决 - Game.fs:LV_FRAME_LOG=1 逐帧日志(墙钟帧间隔 + GC 线程分配增量 + tick/panel), 仅新增日志,不改渲染/更新逻辑 - P70PerformanceBaselineTests:Pin --performance-baseline final_digest=953775FA…(防漂移) - 实测:Kernel tps mean=466679 alloc=3032184 gen0/1/2=0/0/0 determinism=PASS; Desktop 60s frames=8788 fps=139.3 mean=7.179ms max=33.919ms 掉帧>33.3ms=2 每帧分配 mean=231KB p95=297KB;dotnet-counters 缺席已如实标注 - Desktop 338/338、Kernel 120/120;Kernel/Sim/渲染口径/字形表未动
Diffstat (limited to 'docs')
-rw-r--r--docs/evidence/p70-analysis.txt23
-rw-r--r--docs/evidence/p70-env.txt5
-rw-r--r--docs/evidence/p70-frames-sample.txt84
-rw-r--r--docs/evidence/p70-kernel-baseline.txt6
-rw-r--r--docs/evidence/p70-verification.txt49
5 files changed, 167 insertions, 0 deletions
diff --git a/docs/evidence/p70-analysis.txt b/docs/evidence/p70-analysis.txt
new file mode 100644
index 0000000..16541c4
--- /dev/null
+++ b/docs/evidence/p70-analysis.txt
@@ -0,0 +1,23 @@
+P70 启动帧率与渲染绘制概要基准 — 真实可复跑数据
+Kernel:Headless --performance-baseline(已有入口)
+Desktop:xvfb 1280x720 真实帧循环(LV_FRAME_LOG=1,墙钟帧间隔 + 线程分配)
+
+## Kernel 吞吐(Sim.step,6000 measure tick)
+samples=3 digests=3 determinism=PASS
+final_digest=953775FAEB2FDDE97289491AA260BD8D390C571E48A7A13AD2CB6FB7124F7F6C
+ticks_per_second: mean=466679.2 min=278557.2 max=646088.9 n=3
+allocated_bytes: mean=3032184 min=3032104 max=3032344 n=3
+gc collections (last sample): gen0=0 gen1=0 gen2=0
+
+## Desktop 渲染帧(真实帧循环)
+frames_logged=8788
+interval_ms: mean=7.179 min=1.664 max=33.919 p50=7.909 p95=9.847 p99=10.823 std=2.262
+measured_fps=139.3 (frames=8788, wall_ms=63087.3)
+dropped_frames: >25.0ms=4 >33.3ms=2 (0.05% / 0.02%)
+per_frame_alloc_kb: mean=231.22 min=49.40 max=1835.20 p95=297.00
+dotnet-counters=missing
+(帧率随机器/xvfb 软件渲染波动;本报告只列本次实测值,不外推。)
+
+bounds: Kernel/Sim 未改(digest 钉值);Desktop 仅新增 LV_FRAME_LOG 逐帧日志,不改渲染口径/字形表。
+
+verdict: PASS
diff --git a/docs/evidence/p70-env.txt b/docs/evidence/p70-env.txt
new file mode 100644
index 0000000..2178e6b
--- /dev/null
+++ b/docs/evidence/p70-env.txt
@@ -0,0 +1,5 @@
+dotnet-counters=missing
+xvfb-run=available
+bench_seconds=60
+desktop_dll=/home/somhairle/projects/living-village/src/LivingVillage.Desktop/bin/Release/net8.0/LivingVillage.Desktop.dll
+kernel_dll=/home/somhairle/projects/living-village/src/LivingVillage.Headless/bin/Release/net8.0/LivingVillage.Headless.dll
diff --git a/docs/evidence/p70-frames-sample.txt b/docs/evidence/p70-frames-sample.txt
new file mode 100644
index 0000000..c0e6830
--- /dev/null
+++ b/docs/evidence/p70-frames-sample.txt
@@ -0,0 +1,84 @@
+# P70 Desktop 帧日志抽样(完整 8956 行见 /tmp/opencode/lv-p70/desktop-log.txt,可复跑生成)
+# head 40
+world-mode=legacy-64x48 bounds=64x48
+mode=sample seed=42
+controls=WASD move E interact 1-6 choose Q observe Tab needs C chronicle L relations P pause F1/F2/F3 speed F6 save F7 load Esc close/exit
+splash=done frame=150
+p70-frame index=1 ms=3.845 alloc_kb=79.9 tick=0 panel=world
+p70-frame index=2 ms=2.537 alloc_kb=89.5 tick=0 panel=world
+p70-frame index=3 ms=3.371 alloc_kb=80.6 tick=0 panel=world
+p70-frame index=4 ms=2.145 alloc_kb=80.6 tick=0 panel=world
+p70-frame index=5 ms=1.754 alloc_kb=80.6 tick=0 panel=world
+p70-frame index=6 ms=1.664 alloc_kb=80.6 tick=0 panel=world
+p70-frame index=7 ms=1.699 alloc_kb=80.6 tick=0 panel=world
+p70-frame index=8 ms=1.744 alloc_kb=80.6 tick=0 panel=world
+p70-frame index=9 ms=1.723 alloc_kb=80.6 tick=0 panel=world
+p70-frame index=10 ms=1.723 alloc_kb=80.6 tick=0 panel=world
+p70-frame index=11 ms=1.724 alloc_kb=80.6 tick=0 panel=world
+p70-frame index=12 ms=1.957 alloc_kb=80.6 tick=0 panel=world
+p70-frame index=13 ms=1.978 alloc_kb=80.6 tick=0 panel=world
+p70-frame index=14 ms=1.978 alloc_kb=80.6 tick=0 panel=world
+menu=occupation-select
+p70-frame index=15 ms=6.823 alloc_kb=84.4 tick=0 panel=world
+new-game=ok seed=42 npcs=30 occupation=none tick=0
+p70-frame index=16 ms=33.919 alloc_kb=1835.2 tick=0 panel=world
+p70-frame index=17 ms=13.625 alloc_kb=284.2 tick=1 panel=world
+p70-frame index=18 ms=9.052 alloc_kb=284.2 tick=2 panel=world
+p70-frame index=19 ms=10.122 alloc_kb=282.9 tick=3 panel=world
+p70-frame index=20 ms=8.960 alloc_kb=282.9 tick=4 panel=world
+p70-frame index=21 ms=9.781 alloc_kb=282.9 tick=5 panel=world
+p70-frame index=22 ms=12.926 alloc_kb=284.4 tick=6 panel=world
+p70-frame index=23 ms=8.904 alloc_kb=284.4 tick=7 panel=world
+p70-frame index=24 ms=7.907 alloc_kb=284.4 tick=8 panel=world
+p70-frame index=25 ms=20.297 alloc_kb=285.6 tick=9 panel=world
+p70-frame index=26 ms=9.487 alloc_kb=285.6 tick=10 panel=world
+p70-frame index=27 ms=9.017 alloc_kb=285.6 tick=11 panel=world
+p70-frame index=28 ms=9.262 alloc_kb=285.4 tick=12 panel=world
+p70-frame index=29 ms=8.948 alloc_kb=285.4 tick=13 panel=world
+p70-frame index=30 ms=8.775 alloc_kb=285.4 tick=14 panel=world
+p70-frame index=31 ms=9.081 alloc_kb=284.0 tick=15 panel=world
+p70-frame index=32 ms=8.883 alloc_kb=284.0 tick=16 panel=world
+p70-frame index=33 ms=9.031 alloc_kb=284.0 tick=17 panel=world
+p70-frame index=34 ms=8.835 alloc_kb=283.8 tick=18 panel=world
+# ...
+# tail 40
+p70-frame index=8751 ms=8.671 alloc_kb=283.6 tick=3732 panel=world
+p70-frame index=8752 ms=8.935 alloc_kb=283.6 tick=3733 panel=world
+p70-frame index=8753 ms=9.440 alloc_kb=283.6 tick=3734 panel=world
+p70-frame index=8754 ms=8.547 alloc_kb=283.6 tick=3735 panel=world
+p70-frame index=8755 ms=8.476 alloc_kb=285.0 tick=3736 panel=world
+p70-frame index=8756 ms=8.713 alloc_kb=285.0 tick=3737 panel=world
+p70-frame index=8757 ms=8.743 alloc_kb=285.0 tick=3738 panel=world
+p70-frame index=8758 ms=8.500 alloc_kb=285.0 tick=3739 panel=world
+p70-frame index=8759 ms=8.441 alloc_kb=285.0 tick=3740 panel=world
+p70-frame index=8760 ms=8.535 alloc_kb=285.0 tick=3741 panel=world
+p70-frame index=8761 ms=8.481 alloc_kb=285.0 tick=3742 panel=world
+p70-frame index=8762 ms=8.749 alloc_kb=285.0 tick=3743 panel=world
+p70-frame index=8763 ms=8.746 alloc_kb=285.0 tick=3744 panel=world
+p70-frame index=8764 ms=8.610 alloc_kb=285.0 tick=3745 panel=world
+p70-frame index=8765 ms=8.536 alloc_kb=285.0 tick=3746 panel=world
+p70-frame index=8766 ms=8.193 alloc_kb=285.0 tick=3747 panel=world
+p70-frame index=8767 ms=8.657 alloc_kb=285.0 tick=3748 panel=world
+p70-frame index=8768 ms=8.948 alloc_kb=285.0 tick=3749 panel=world
+p70-frame index=8769 ms=8.737 alloc_kb=285.0 tick=3750 panel=world
+p70-frame index=8770 ms=9.309 alloc_kb=283.6 tick=3751 panel=world
+p70-frame index=8771 ms=8.558 alloc_kb=283.6 tick=3752 panel=world
+p70-frame index=8772 ms=8.383 alloc_kb=283.6 tick=3753 panel=world
+p70-frame index=8773 ms=8.970 alloc_kb=283.6 tick=3754 panel=world
+p70-frame index=8774 ms=8.810 alloc_kb=283.6 tick=3755 panel=world
+p70-frame index=8775 ms=8.349 alloc_kb=283.6 tick=3756 panel=world
+p70-frame index=8776 ms=8.374 alloc_kb=283.6 tick=3757 panel=world
+p70-frame index=8777 ms=8.291 alloc_kb=283.6 tick=3758 panel=world
+p70-frame index=8778 ms=8.504 alloc_kb=283.6 tick=3759 panel=world
+p70-frame index=8779 ms=8.121 alloc_kb=283.6 tick=3760 panel=world
+p70-frame index=8780 ms=8.564 alloc_kb=283.6 tick=3761 panel=world
+p70-frame index=8781 ms=8.339 alloc_kb=283.6 tick=3762 panel=world
+p70-frame index=8782 ms=8.307 alloc_kb=283.6 tick=3763 panel=world
+p70-frame index=8783 ms=8.792 alloc_kb=283.6 tick=3764 panel=world
+p70-frame index=8784 ms=8.509 alloc_kb=283.6 tick=3765 panel=world
+p70-frame index=8785 ms=9.034 alloc_kb=285.0 tick=3766 panel=world
+p70-frame index=8786 ms=8.682 alloc_kb=285.0 tick=3767 panel=world
+p70-frame index=8787 ms=8.671 alloc_kb=285.0 tick=3768 panel=world
+p70-frame index=8788 ms=8.516 alloc_kb=285.0 tick=3769 panel=world
+sample stage=SampleComplete tick=3769 pos=(1019,821)
+sample result=ok
diff --git a/docs/evidence/p70-kernel-baseline.txt b/docs/evidence/p70-kernel-baseline.txt
new file mode 100644
index 0000000..c43281a
--- /dev/null
+++ b/docs/evidence/p70-kernel-baseline.txt
@@ -0,0 +1,6 @@
+performance_config seed=42 npc_count=4 warmup_ticks=120 measure_ticks=6000 repetitions=3 input_pattern=8-direction-cyclic
+performance_runtime framework=.NET 8.0.31 version=8.0.31 os=Pop!_OS 24.04 LTS architecture=X64 stopwatch_frequency=1000000000
+performance_sample repetition=1 seed=42 npc_count=4 warmup_ticks=120 measure_ticks=6000 elapsed_stopwatch_ticks=21539565 stopwatch_frequency=1000000000 elapsed_seconds=0.021539565 ticks_per_second=278557.157 allocated_bytes=3032344 gen0=0 gen1=0 gen2=0 final_tick=6120 final_digest=953775FAEB2FDDE97289491AA260BD8D390C571E48A7A13AD2CB6FB7124F7F6C runtime=.NET 8.0.31 runtime_version=8.0.31
+performance_sample repetition=2 seed=42 npc_count=4 warmup_ticks=120 measure_ticks=6000 elapsed_stopwatch_ticks=12621178 stopwatch_frequency=1000000000 elapsed_seconds=0.012621178 ticks_per_second=475391.441 allocated_bytes=3032104 gen0=0 gen1=0 gen2=0 final_tick=6120 final_digest=953775FAEB2FDDE97289491AA260BD8D390C571E48A7A13AD2CB6FB7124F7F6C runtime=.NET 8.0.31 runtime_version=8.0.31
+performance_sample repetition=3 seed=42 npc_count=4 warmup_ticks=120 measure_ticks=6000 elapsed_stopwatch_ticks=9286647 stopwatch_frequency=1000000000 elapsed_seconds=0.009286647 ticks_per_second=646088.949 allocated_bytes=3032104 gen0=0 gen1=0 gen2=0 final_tick=6120 final_digest=953775FAEB2FDDE97289491AA260BD8D390C571E48A7A13AD2CB6FB7124F7F6C runtime=.NET 8.0.31 runtime_version=8.0.31
+performance_determinism=PASS
diff --git a/docs/evidence/p70-verification.txt b/docs/evidence/p70-verification.txt
new file mode 100644
index 0000000..6794edc
--- /dev/null
+++ b/docs/evidence/p70-verification.txt
@@ -0,0 +1,49 @@
+P70(启动帧率与渲染绘制概要基准)验证记录
+基线:commit 1d56991(P69)。本单未 push。
+
+目标与可见性
+- 为「性能吞吐/分配/GC 基准与真实数据」补一组真实可复跑的 Desktop 侧基准;本单可在桌面/dev UI 观看。
+- 不宣称未测性能:只列本次实跑数字,未测项如实标注。
+
+改动
+- src/LivingVillage.Desktop/Game.fs:新增 LV_FRAME_LOG=1 逐帧日志(仅日志,不改渲染/更新逻辑)——
+ 每帧打印墙钟帧间隔 `ms`、线程分配增量 `alloc_kb`(GC.GetAllocatedBytesForCurrentThread)、
+ tick 与当前 panel。配合 LV_PERF_SOAK_SECONDS + LV_AUTOPLAY_SAMPLE + LV_UNLOCK_FPS 跑 N 秒真实帧循环。
+- src/LivingVillage.Kernel.Tests/P70PerformanceBaselineTests.fs(新):Pin Headless --performance-baseline
+ 最终 digest = 953775FA…(防 Kernel/Sim 漂移)+ fsproj 挂载。
+- scripts/bench-p70.sh(新):Kernel 吞吐 + Desktop 60s xvfb 帧循环两档,落盘后调 analyzer。
+- scripts/analyze-p70.py(新):汇总数字与裁决,写 docs/evidence/p70-analysis.txt。
+
+命令 / 环境 / 输入
+- 构建:dotnet build LivingVillage.sln -c Release
+- 基准:P70_SECONDS=60 bash scripts/bench-p70.sh /tmp/opencode/lv-p70
+ - Kernel:dotnet src/LivingVillage.Headless/bin/Release/net8.0/LivingVillage.Headless.dll --performance-baseline
+ (seed=42 npc=4 warmup=120 measure=6000 ×3)
+ - Desktop:xvfb-run -a -s "-screen 0 1280x720x24" env LV_AUTOPLAY_SAMPLE=1 LV_PERF_SOAK_SECONDS=60
+ LV_FRAME_LOG=1 LV_UNLOCK_FPS=1 LV_LEGACY_MAP=1 LV_RECORD_DIR=... dotnet .../LivingVillage.Desktop.dll
+- 环境:linux,Xvfb 软件渲染(llvmpipe),1280x720;dotnet-counters=missing(逐帧分配改由进程内
+ GC API 实测,非 counters)。
+
+实测数字(本次,不外推)
+- Kernel 吞吐(6000 tick ×3):ticks_per_second mean=466679 / min=278557 / max=646089;
+ allocated_bytes mean=3032184;gc gen0/1/2=0/0/0;determinism=PASS;final_digest=953775FA…7F6C(钉值一致)。
+- Desktop 帧循环(60s,解锁 vsync/固定步长):frames=8788,wall=63087ms,measured_fps=139.3;
+ frame interval ms mean=7.179 / min=1.664 / max=33.919 / p50=7.909 / p95=9.847 / p99=10.823 / std=2.262;
+ 掉帧 >25ms=4(0.05%)、>33.3ms=2(0.02%);每帧分配 KB mean=231.22 / p95=297.00 / max=1835.20。
+- 说明:帧率依赖机器与 xvfb 软件渲染,本报告只列实测,不设硬性 fps 门槛。
+- 未测项:dotnet-counters 缺席 → live counters 无;已用 GC API 替代给出每帧分配。
+
+复现
+ dotnet build LivingVillage.sln -c Release
+ P70_SECONDS=60 bash scripts/bench-p70.sh /tmp/opencode/lv-p70
+ cat docs/evidence/p70-analysis.txt # verdict 应为 PASS
+
+验收
+- dotnet build -c Release → 0 错误,1 警告(P40ArtTests.fs FS0760,既有)。
+- Desktop 338/338(--no-build);Kernel 120/120(--no-build,含新增 Pin 1 例)。
+- p70-analysis.txt verdict=PASS,含真实数字(见上)。
+
+边界
+- 未改 Kernel/Sim 数值路径、渲染口径、字形表、地图生成;未 push。
+- 提交物:脚本 + 证据(analysis/env/kernel-baseline/帧日志抽样)+ 1 条 pin 测试 + 仅日志式的 Game 帧记录。
+- 完整 8956 行帧日志在 /tmp/opencode/lv-p70/desktop-log.txt(复跑生成),仓库内留 head/tail 抽样。