街区渲染性能优化(2026-10-08)
后续优化的优先级、复测命令、验收规则与 Goal 模板见游戏性能优化手册。本文保留各轮实现、实测与验证边界。
省二医附近的桌面骑行缓存帧原为 337 次绘制,超过已有 300 次门槛。本次按实际绘制来源优化座舱和短跨桥护栏,桌面降至约 234 次,减少约 31%;医院骑行与步行视角都按原有 <300 calls / <90,000 triangles 断言,不提高预算。
改动与代价
render/cockpitBatch.ts合并车身、转向架、握把和刹车各自的刚性零件;仪表盘、刹车转轴、动态线管和可选皮肤继续保留各自的更新/可见性边界。- 手臂、手指和腿部的方盒零件按共享材质实例化,沿原有动画骨架更新实例矩阵。姿态不变时不上传矩阵;下车、游览和进入建筑时不更新隐藏的骑手实例。座舱绘制从 67 次降为 33 次,几何数量保持一致。
- 原来每约 4 m 独立绘制的道路跨水护栏,改按 120 m 空间格合批,保留每段破坏 ID 和几何范围。碰撞、单段破坏和恢复继续使用原契约。
- 护栏格使用 470 m 保守可见半径,覆盖原先每段 380 m 的范围,因此可能多画邻近格内的护栏。缓存帧三角形从约 64,500 增至约 68,000,换取更少提交;没有简化医院、降低分辨率或修改水面刷新质量。
预算与实测
继续以桌面 60 fps(16.7 ms/帧)、手机 30 fps(33.3 ms/帧)为目标。缓存帧门槛和水面捕获刷新帧分别统计,不能用暂停后的缓存数值代表所有运行帧。
基线与缓存回归使用桌面 1440 × 900、手机 390 × 844 的浏览器视口,均设置 720p / 30 fps、晴天正午,医院西侧停稳后暂停并等待水面捕获稳定。绘制总数包含世界、阴影、第一人称和最终呈现;车流等变化会带来少量波动。
| 骑行缓存视角 | 优化前调用 | 最终回归调用 | 最终回归三角形 |
|---|---|---|---|
| 桌面 | 337 | 234 | 67,810 |
| 手机 | 216–218 | 182 | 58,416 |
最终步行缓存帧:桌面 228 次/65,812 三角形,手机 174 次/55,634 三角形。此前优化采样中手机骑行为 177–182 次,差异来自可见车流等变化。
运行采样使用本机 Apple M1 Pro / ANGLE Metal,两个视口串行运行,开始状态确认为 playing,医院西侧停稳、热身 3 秒后各采样 120 帧。桌面设置 1080p / 60 fps,实际绘制缓冲 1440 × 900;手机设置 720p / 30 fps,实际缓冲 390 × 844。使用一条 GPU 查询覆盖整帧提交,包含反射、折射、阴影和呈现。
| 运行采样 | 桌面视口 | 手机视口 |
|---|---|---|
| 平均帧率 | 60.0 fps | 30.0 fps |
| 帧间隔中位数 / P95 | 16.6 / 17.7 ms | 33.3 / 34.0 ms |
| GPU 整帧中位数 / P95 | 4.65 / 8.41 ms | 1.77 / 3.75 ms |
| 采样内最大调用(含水面捕获) | 294 | 222 |
| 采样内最大三角形 | 78,278 | 67,152 |
这些结果证明该机位在本机的提交数量和短时帧率;不代表整个地图、连续高速行驶或实体手机表现,也不能据此声称帧率提升了 31%。帧间隔包含 CPU、GPU、限帧和系统调度;GPU 查询只测提交范围的 GPU 工作,不能与 CPU 提交耗时直接相加。
GPU 与复测
游戏的 WebGL 渲染本来就在浏览器 GPU 上运行。实例化把多份几何的绘制交给 GPU,减少 CPU 提交;本次没有把 Rapier 物理迁移到 GPU,也没有新增云 GPU 服务。
本地原生 GPU 浏览器检查使用单 worker:
pnpm exec playwright test e2e/hospital.spec.ts e2e/jianghai-interchange.spec.ts e2e/water-rendering.spec.ts e2e/vehicle-interaction.spec.ts --config playwright.gpu.config.tsplaywright.gpu.config.ts 在 macOS 使用完整 Chromium 与 ANGLE Metal;其他平台使用完整 Chromium 的自动后端。以附件中的 gpu 字段确认实际设备,不能仅凭配置文件判断 GPU 已启用。普通 CI 配置保持原样;性能采样与其他 WebGL 测试串行运行,避免争用同一 GPU。
开发街区页面新增临时采样接口:
// 整帧 GPU 耗时、帧间隔及各阶段的 CPU 提交/绘制数
const profile = await window.__DISTRICT_DEBUG__.profile(120);
// 需要定位 GPU 阶段时另做一次采样;不与上一次重叠
const passes = await window.__DISTRICT_DEBUG__.profile(60, "passes");默认结果的 gpuFrameMs 为整帧 GPU 时间;samples 按世界、座舱、反射、折射、呈现分组,并单列阴影提交。"passes" 模式改测各阶段的 gpuMs,不将阶段之和当作整帧测量。第一帧保存实际绘制对象名,方便定位碎片网格。EXT_disjoint_timer_query_webgl2 不可用、上下文丢失或计时无效时保留 null,不使用阻塞式 finish / readPixels 补测。
采样结束或超时会恢复所有钩子、释放查询;未采样时没有持续查询工作。接口只随开发诊断模块加载,发布产物校验检查诊断代码未进入生产构建。
验证
相关单测覆盖实例与原动画世界变换、左右踢击与体型变化、皮肤和装备切换、固定零件合批边界、护栏单段破坏/恢复、采样超时清理及 GPU 计时失效。浏览器检查覆盖医院昼夜、桌面/手机骑行预算、桥下通行、上下车、真实水面反射、浮点扩展降级及 GPU 上下文恢复。
相关单测与应用类型检查通过。医院、江海立交、水面和上下车共 11 个相关浏览器用例已通过;修正上下车用例在剧情站点附近触发交谈的测试机位后,该项单独复测通过。最终医院桌面/手机两项再次通过,并各返回 30 条有效整帧 GPU 计时。一次开发服务器热重载中断了手机采样,最终使用关闭热重载与文件监听的独立服务器完成复测。
pnpm build、pnpm verify:performance、pnpm verify:release 和 git diff --check 通过。最终构建首屏 JS 295.5 KiB gzip/350 KiB,街区入口 317.9 KiB/350 KiB,街区 CSS 8.8 KiB/16 KiB,完整游戏资源 12.00 MiB/20 MiB;202 个发布文件校验通过,开发诊断未打包。本次未执行完整 release:check 或实体手机长时间测试。医院来源与建模参数见省二医建模文档。
2026-10-09 静态合批可见面剔除
本节记录首轮优化及其当时的验证结果;同日继续处理跨格合批和冷启动的结果见下一节。
本次继续处理已记录的街区三角形超限。120 m 楼体合批只要部分进入视野,原来就会提交整批窗格和檐台;远处广州塔也提交整段轮廓的背面。通用楼体详细批次和广州塔基础轮廓现在按每个实际渲染相机选择原部件,保留与视锥相交的包围盒,再依据材质的 FrontSide / BackSide / DoubleSide 选择可能栅格化的原始三角面。没有减少模型细节或修改预算。
render/staticBatch.ts 的可选 cameraCulling 仅在上述两处启用;staticBatchCulling.ts 预计算部件边界和三角面平面,复用同一索引缓冲。主画面、反射和折射使用各自相机;阴影使用阴影相机及实际深度材质的面向规则。初始索引、完整模型边界和破坏 ID / 几何范围保留,相机空子集不隐藏整张网格,后续视角与毁坏恢复可以重新选择。相同投影和材质状态复用上一结果,逐帧不创建数组或向量。诊断采样的首帧 draws 同时记录实际 calls 和 triangles,方便继续定位开销。
同机位对照使用 Apple M1 Pro / ANGLE Metal、1440 × 900、720p / 60 fps、晴天正午;每次放置后等待 1 秒,再采样 60 个完整运行帧,包括水面刷新、阴影、座舱及最终呈现。表内分别取调用和三角形的最大值,二者不保证来自同一帧。车流仍有少量变化。
| 机位(x, z, yaw) | 原三角形峰值 | 优化后三角形峰值 | 最终调用峰值 |
|---|---|---|---|
| 滨江街道(44.73, −702.35, −0.323) | 106,106 | 76,493 | 175 |
| TIT 西门(−131.5, −72, 0) | 102,019 | 70,961 | 238 |
| 丽园圆庭(114, −80, 0) | 98,974 | 68,439 | 248 |
| 小米骑行视角(2130, −720, π/2) | 96,119 | 80,081 | 271 |
四机位的三角形提交量减少约 17%–31%,不把该比例当作帧率提升。390 × 844 触屏视口中,同四机位最终最高 214 calls / 64,539 triangles;截图检查无横向溢出,页面错误和框架错误遮罩均为 0。这些仍是本机 GPU 的手机视口模拟,不代表实体手机验收。新增一次性的索引和面平面缓存;本轮未重测弱网冷启动、持续内存或手机温度。
最终全仓类型检查、172 个文件 / 1047 项单测、构建、现有体积预算、发布产物及 Git 资源检查通过。单测包含双面和反面材质、正交阴影、反射位置、父级镜像、毁坏恢复,以及精简索引与完整实塔几何的射线命中对照。首轮单测在浏览器回归并行运行时有一项街道规划超时,限制为 4 个 worker 后按原超时门槛全量通过。最终产物首屏 300.4 KiB gzip、街区入口 335.1 KiB、合作入口 347.8 KiB,完整游戏资源 12.89 MiB;365 个发布文件检查通过,诊断代码未打包。
首轮 29 项 GPU E2E 为 25 通过、4 项预算失败;继续优化后,最终定向 13 项为 11 通过、2 项仍失败。TIT 西门、丽园桌面和手机、水面捕获 / 降级 / 恢复、实际炮击建筑与栏杆、完整广州塔视角及总部游览已通过。街道灯光机位测到 301 calls,腾讯跨街日景捕获峰值测到 347 calls,仍未满足 <300 calls;总部完整预算用例因该调用断言失败,不能据单独小米机位声称总部所有机位均通过。整体性能待办继续保留,15 秒街区冷启动、实体设备与完整发布门禁本轮未验收。
复测使用现有 playwright.gpu.config.ts 的单 worker;最终定向覆盖 district 的西门 / 街道灯光、liyuan、internet-headquarters、water-rendering、tank-combat 的碰撞 / 实际建筑与栏杆炮击,以及 tower-visit 的完整塔视角用例。三角形优化与剩余调用问题分别记录在待办。
2026-10-09 跨格合批与冷启动复测
街道、交通设施和通用楼体详细网格现在跨空间格共享静态绘制,保留原格和破坏对象的可见性。水面层仍先按原格分类,再合并相同材质、层、阴影和属性的网格;动画灯光、碰撞和破坏范围继续独立。琶洲地标基础与详细网格也启用各实际相机的部件和面剔除。腾讯跨街的旧日景基线为 347 calls / 95,152 triangles,夜景为 348 / 95,710;原用例先在调用断言失败,三角形也超限,不能只记录调用数。
最终预算用例按每帧采样 800 ms,覆盖 5 Hz 水面刷新及阴影和座舱。街道三个机位、昼 / 晚 / 夜及两轮热资源复测共 18 组均通过,最高 252 calls / 82,224 triangles,每组采到 41–49 帧。总部七个机位的昼夜共 14 组均通过,最高 259 calls / 62,404 triangles;腾讯跨街日景为 259 / 61,962,夜景为 259 / 62,404。全部沿用 <300 calls / <90,000 triangles 原门槛,并检查热身后几何和纹理没有持续增加。
静态合批直接把索引源和非索引源写入最终属性数组,避免先展开、克隆、变换再合并的重复拷贝;特殊属性继续使用原路径。标准位置、法向、切线、归一化整数和自定义属性均与独立旧算法逐属性对照,源几何保持只读。面平面在相机首次需要时计算并缓存,远处和双面部件无需在启动时计算。通用楼体取消中间的逐格烘焙,只在最终共享批次烘焙一次。
完全隐藏的部件范围首次清除后不再逐三角形扫描;重建索引只遍历参与当前相机绘制的范围,并保持原顶点顺序。完整且不重叠的范围采用此路径,其他范围保留原全扫描处理。每次仅向 GPU 更新实际绘制的索引前缀,复用同一更新范围对象;空视野保留此前尚未消费的上传状态,后续非空相机重写有效前缀,首次创建和上下文恢复仍上传完整缓冲。独立旧算法与 GPU 缓冲状态模型覆盖相机、材质侧面、阴影、隐藏、毁坏及恢复后的逐索引一致性。
专门的稀疏可见 Node 基准包含 512 格、196,608 个三角形和 2.36 MB 索引,连续切换 120 次相机并重复五轮。索引计算中位数由 83.183 ms 降至 2.307 ms,模拟后续索引更新量由 283.1 MB 降至 0.916 MB;首次完整缓冲上传仍保留。这些是该基准的 CPU 和数据量,不能当作游戏帧率或真实 GPU 时间。
加载器提前请求五份地图和 Rapier,在主游戏包下载和同步规划时继续传输;失败保留原加载错误与重试流程。水域环按空间带建立索引,道路、建筑和园路预计算线段;放置阈值只在已经确定不合格时提前结束,远处边界用保守包围盒跳过,交通设施使用局部家具索引。五份地图独立完整数组对照为 5652 个装饰点、18373 段路缘、120 个标志和 37 个路口,均与旧版相同;水域 14,973 个边界和附近点的判断也保持一致。
第一次集成复测使用 Apple M1 Pro / ANGLE Metal、手机视口、禁用网络缓存、Fast 3G(1.6 Mbps 下载 / 750 Kbps 上传 / 150 ms RTT)和 4 倍 CPU 节流。旧路径静态合批约 4.546 秒,直接烘焙后约 2.710 秒;街道规划由约 2.337 秒降至 1.382 秒。直接烘焙版本两次真实首帧为 16,764 / 16,947 ms,同条件 Git HEAD 无 profile 对照为 19,044 ms。相应 district:first-frame 标记为 14,917 / 14,980 ms,尚不能满足包括点击后两次 RAF 的 15 秒门槛。另一次 HEAD profile 出现约 5 秒的音频恢复异常,已补正常对照,不用该异常样本计算收益。
这次集成版本的原样 playwright.performance.config.ts 在本机实际使用 SwiftShader / Vulkan:街区真实首帧 38,718 ms(首帧标记 16,800 ms);首页首次可用 11,220 ms,但进入比赛首帧 25,993 ms。因此原配置两项均失败,不能用 Metal 的结果替代标准性能验收。原门槛、配置、分辨率和限帧保持不变。
加入隐藏范围跳过及索引前缀上传后,最终同条件 Metal 两次真实首帧为 17,362 / 16,671 ms,首帧标记为 15,655 / 15,021 ms;与前一版的波动范围接近,未证明进一步的冷启动改善。原样性能配置的街区真实首帧为 39,274 ms(标记 17,736 ms),首页首次可用 11,411 ms、比赛首帧 27,318 ms,两项仍失败。这些测量独占执行,并确认实际 GPU;冷启动待办继续保留,不以加载标记、包体通过或局部索引基准替代真实可操作时间。
最终全仓类型检查、177 个文件 / 1061 项单测、构建、体积预算、366 个发布文件校验及 Git 资源策略检查通过。首屏 JS 为 301.3 KiB gzip / 350 KiB,街区入口 337.1 KiB / 350 KiB,合作入口 349.0 KiB / 350 KiB,完整游戏资源 12.90 MiB / 20 MiB;开发诊断未进入发布产物。没有提高预算或修改资源许可。
最终原生 GPU 定向 E2E 17 / 17 通过:加载器与重试、TIT 西门与街道花池碰撞、街道全帧预算、全部总部机位与游览、丽园桌面 / 手机、实际弹丸碰撞与建筑 / 桥栏破坏、完整广州塔视角、水面反射与裁剪、手机浮点降级和上下文恢复、河流与水池捕获预算。复测使用现有单 worker GPU 配置;本轮启用 trace 留存各预算样本,不改断言和超时。浏览器插件不可用,使用已有 Playwright。上述定向回归通过不代表完整 release:check;标准冷启动性能两项仍失败,实体手机尚未验收。
桌面 1440 × 900 和触屏视口 390 × 844 的真实加速、刹车、暂停恢复及地图主题切换均通过。页面地址和标题正确,画布与 HUD 明确渲染,没有页面 / 控制台错误、框架遮罩或横向溢出,四张截图逐张检查通过。
最终运行采样仍使用 Apple M1 Pro / ANGLE Metal,串行执行,无其他浏览器或重测试争用。两视口均以 60 fps 设置采样:各机位先热身 1.5 秒,再采 180 个完整运行帧,实际绘制缓冲分别为 1214 × 758 和 390 × 844。每组包含 14–15 次水面捕获,180 条整帧 GPU 查询全部有效;平均帧率为 59.98–60.04 fps。调用、三角形各取独立峰值。
| 视口 / 机位 | 调用 / 三角形峰值 | 帧间隔 P95 | 整帧 GPU P95 | 渲染 CPU 提交 P95 |
|---|---|---|---|---|
| 桌面 / 街道黄昏 | 251 / 80,609 | 17.8 ms | 6.67 ms | 5.2 ms |
| 桌面 / 腾讯跨街日景 | 252 / 59,857 | 17.7 ms | 7.47 ms | 5.3 ms |
| 桌面 / 腾讯跨街夜景 | 252 / 60,299 | 18.8 ms | 7.28 ms | 4.9 ms |
| 触屏视口 / 街道黄昏 | 199 / 48,968 | 17.4 ms | 2.88 ms | 4.6 ms |
| 触屏视口 / 腾讯跨街日景 | 190 / 45,309 | 19.2 ms | 3.21 ms | 4.7 ms |
| 触屏视口 / 腾讯跨街夜景 | 192 / 45,767 | 20.2 ms | 3.20 ms | 4.9 ms |
最大帧间隔为 22.1 ms,存在波动;短时采样未见共享合批的逐相机处理阻塞当前 60 fps 运行。GPU 时间与 CPU 提交时间不能相加当作帧时间,亦不声称索引基准带来了相同幅度的游戏帧率提升。触屏视口仍由 M1 Pro 渲染,不代表实体 Android / iPhone、持续高速行驶、内存和温度验收。
2026-10-10 移动帧 CPU 开销与自动分辨率
本轮针对 Mac 骑行卡顿检查当前工作树,保留此前的合批与资源策略。renderFrame 仅更新可见分支的世界矩阵;隐藏分支重新显示时补齐变换,并保留隐藏期间祖先的手动矩阵更新。各 layer、视锥外的可见对象仍更新,供阴影、反射与折射使用;可见灯光的 target 单独刷新。碰撞、射线和建模需要隐藏几何时仍使用 Three.js 完整矩阵更新。后视镜在主画面已更新矩阵后复用同一结果,独立调用仍保留自动更新,异常路径恢复原状态。
公交站棚和停车区的矩阵、颜色在创建时缓存,可见站点集合变化时才重排和上传;人物、车辆、轮胎及接触阴影只上传实际实例前缀,空批次不产生新的上传。固定站点集合的 120 帧独立回归,原先 1,800 次矩阵重建降为 0;人物上传字节测试低于原整池的 50%,实际动画、剔除和恢复的矩阵/颜色摘要与修改前相同。城市合作僵尸插值在收到快照时建立 Map,避免每个显示帧反复线性查找上一快照。
比赛、街区及两种合作模式的自动分辨率按持续帧间隔调整:至少 1.5 秒窗口和 24 帧才评估,持续低于目标时将像素倍率乘以 0.85,最低为基础倍率的 0.6(36% 像素数);恢复使用较长稳定窗口。只在实际游戏运行且选择「自动」时调节,菜单、暂停、后台间隔和单次长卡顿不参与。手动分辨率、设置持久化和 DOM UI 清晰度保持;设置变化、尺寸变化和 GPU 恢复重置自适应状态。自适应最高以 60 fps 判断,避免在 60 Hz 显示器上为了追逐 120 fps 一直降画质。双人合作同时遵循共享限帧与手动像素预算;城市合作复用街区的基础像素上限。
探索性采样使用本机 Apple M1 Pro / ANGLE Metal、1440 × 900 Retina 视口、自动分辨率 / 60 fps、晴天正午。腾讯跨街停稳热身 2 秒后采 180 帧;医院西侧持续加速热身 1.8 秒后采 300 帧,同时记录 CDP CPU profile。水面、阴影、座舱和呈现均包含在 GPU 查询内。
| 版本/骑行样本 | 最终缓冲 | 帧间隔中位数 / P95 | GPU 整帧 P95 |
|---|---|---|---|
| 本轮修改前 | 1959 × 1224 | 41.5 / 48.7 ms | 16.57 ms |
| 仅可见矩阵更新 | 1959 × 1224 | 22.7 / 31.9 ms | 15.68 ms |
| 全部改动首次采样 | 1175 × 734 | 37.8 / 58.1 ms | 10.48 ms |
| 全部改动重复采样 | 1175 × 734 | 33.3 / 46.5 ms | 10.27 ms |
采样期间发现机器上还有其他 Chromium / SwiftShader 测试进程竞争 CPU 与 GPU,各轮不能作为独占硬件的严格 A/B;相同显示帧数对应不同骑行时长和终点,自动分辨率也在窗口中变化。以上仅记录观测,不据此声称固定帧率提升比例或已达到全地图稳定 60 fps。CPU profile 中原先占首位的隐藏世界矩阵更新已消除,静态面剔除和 Rapier 查询仍是后续热点。未降低物理更新频率、简化碰撞或改变水面刷新频率。
验证:9 个相关单测文件 / 40 项通过,全仓类型检查、pnpm build、441 个 Web 发布文件检查、Git 资源策略和 diff 格式检查通过。原生 GPU 回归已覆盖桌面/手机公交、医院昼夜、上下车、水面反射与 GPU 恢复、双人合作和城市合作。实际自动负载/手动分辨率/暂停恢复烟测使用 1440 × 900 与 390 × 844 两个视口:自动模式持续负载后缩小缓冲,切换手动 720p 后缓冲保持,真实加速与恢复正常;地址、标题、画布、HUD、控制台、框架遮罩和横向溢出检查通过。浏览器插件未提供,使用已有 Playwright 与 Metal 配置;桌面和手机视口截图逐张检查。
体积预算保留原门槛:首屏 JS 309.2 KiB、街区 JS 343.1 KiB、城市合作 JS 346.6 KiB,均低于 350 KiB;首屏 CSS 16.1 KiB 高于 16 KiB,完整性能预算未通过,未提高预算。其余入口与资源体积检查通过,完整游戏资源 13.43 MiB。没有执行完整 release:check、重新打包已安装客户端、Windows 对照或实体手机长时间验收;标准弱网冷启动待办继续保留。
2026-10-10 后视镜默认与共享画面设置
后视镜保持每次进入街区默认关闭,用户手动开启才加载渲染模块,关闭状态不提交后视镜画面。地图 → 设置 → 画面新增当前后视镜开关,与工具栏/V/手柄共享同一状态;步行、坦克、室内与游览时禁用。
共享画面设置提供自动动态分辨率,以及 540p、720p、900p、1080p、1440p、2160p;各选项标注标准尺寸。档位限制的是 3D 画布总像素,保持当前窗口比例,并受设备像素比上限限制;DOM 文字清晰度不变。原生窗口仍可拖动调整或全屏。帧率档位为 30、60、90、120、144 和不限;不限跟随屏幕的动画回调,不承诺超过屏幕刷新率。默认自动+60 FPS,手动设置立即生效并跨页面保存。首页/比赛、街区及两类合作模式共用设置,合作暂停菜单按需加载面板。
水面筛选缓存各叶节点的世界包围球与包围盒,按世界矩阵、几何引用、位置属性引用/上传版本刷新。沿用原球体视锥判定、最近水面选择及河流 650 m/水池 100 m 门槛,保持反射/折射分辨率与捕获频率。两片静态水面在 120 个移动相机帧中仅首次各变换一次包围球和包围盒,额外 updateWorldMatrix 调用为零;父节点移动、隐藏、普通/交错位置属性更新和几何替换均有回归。该计数证明减少重复计算,不换算为固定 FPS 提升。
后续主要 CPU 优化方向仍是静态面剔除的共享祖先可见性/矩阵逆缓存,以及 Rapier 场景查询更新;应先保留剔除参考对照和车辆碰撞回归,再逐项测量。HUD 已低频更新,可以继续减少未变化的快照引用,但预期收益较小。
验证:10 个相关单测文件/81 项通过,17 个相关浏览器用例通过;覆盖桌面 1440 × 900、手机 390 × 844、横屏 844 × 390、手柄、语言切换、设置保存和即时像素预算、镜子默认/开关/迟到响应、水面反射/折射与 GPU 恢复、真实双人合作以及本地城市暂停。合作输入另补 Select/Dialog Escape 与原生事件传播回归;显示面板直接使用共享翻译实例,兼容不安装翻译插件的合作入口。初次集成发现这两个缺口并修复;长联机流程改为关闭 HMR 的开发服务器,本地暂停验证使用构建产物,避免并行编辑重载退出房间以及联机规则继续运行导致倒地。Browser plugin not available,使用已有 Playwright Chromium / ANGLE Metal;截图在 /tmp/dayun-display-settings-20261010 与 /tmp/dayun-kicker-city-coop-playtest,逐张检查可读性、滚动、焦点和溢出。
构建、全仓类型检查、449 个 Web 发布文件、Git 资源策略与格式检查通过;最新同一工作树性能预算通过,首屏 JS 310.1 KiB、CSS 15.8 KiB、街区 JS 346.8 KiB、城市合作 JS 347.4 KiB,保持原门槛。没有重新打包已安装客户端或进行 Windows/实体手机对照;仍不声称稳定 60 FPS。
2026-10-10 刚体步进与共享可见性
本轮先采样连续骑行的 CPU 调用树,再处理实际热点。沿用 WebGL 最佳实践的减少重复工作和缓冲上传方向,以及 Rapier 公开的 PhysicsPipeline.step。现有 Rapier 本来就是 Rust/WASM;继续降低绑定层开销比重写整个游戏更直接。
刚体世界
Rapier 0.21.0 的 World.step 在完整物理步进后无条件调用 mapNewSoftBodies,扫描刚体、碰撞体及关节的 JS 包装对象,以同步软体撕裂产生和删除的对象。街区没有软体,公开的创建、删除和快照恢复 API 已维护这些包装对象;医院连续骑行的初始 CPU profile 中,World.step 累计约 1,068 ms,其中这次同步约 1,045 ms。
physics/stepWorld.ts 在没有软体时直接调用同一公开物理管线,保留原步长、重力、求解、CCD、场景查询更新、事件和 hooks;存在软体(包括禁用的软体)时回退官方 World.step。街区骑行、街道车辆、广州塔和地铁室内复用它,不合并或删除原有步进,不降低物理频率。升级 Rapier 时必须复核 World.step 的新增职责并运行真实 WASM 等价测试,不能把该优化当作所有版本的通用替代。
独立浏览器专项基准使用 4,002 个碰撞体和一个运动学体,每轮 120 步;热身后交替执行两个路径七轮,官方同步次数为 840,优化路径为 0。中位耗时由 53.1 ms 降至 0.8 ms,最终物理快照逐字节一致。该结果来自以静态碰撞体为主的物理专项,不能换算成游戏帧率或复杂动态场景的固定提升倍数。
真实 WASM 回归覆盖动态/运动学运动、CCD、角色扫掠和查询、碰撞体禁用/变形/移动/删除/重建、快照恢复、两种关节及级联删除、碰撞/接触力事件、hooks,以及软体启停、撕裂后生成对象的有效性和全部移除后的快速路径。Vitest 仅对 Rapier 精确启用依赖内联,保证 WASM 及 JS 回调使用同一模块实例。
静态合批
原来每个范围都会沿祖先链检查显隐,很多范围共享同一个空间格。现在初始化时编译共享祖先树,每个实际渲染 pass 按需读取可见分支;隐藏子树首次清除后直接跳过,叶范围显隐真正变化才重建索引。不能按显示帧缓存显隐,因为反射、阴影等相机可能临时切换它。静态网格的逆矩阵只在世界矩阵变化时更新;父级移动、旋转和镜像仍精确失效。完整边界、破坏 ID、原始顶点顺序、材质侧面及上传前缀行为保持。
稀疏城市专项包含 512 格、8,192 个部件、98,304 个三角形,24 格可见,每轮 240 次主画面/阴影相机回调。两个版本使用独立 Node 进程,热身后各七轮并交替复测:原路径中位数 23.76/24.88 ms,优化后 17.17/18.33 ms,减少约 26%–28% 此基准的 CPU 时间。最初的全节点缓存实现曾比原路径慢,已改为隐藏子树短路;不根据祖先读取次数单独声称性能提升。既有逐索引参考、模拟 GPU 上传、反射/阴影、破坏恢复及射线对照继续通过。
游戏内前后对照
最后一轮关闭 CDP CPU 分析器,串行运行旧/新路径,以免采样器和同时运行的 GPU 测试干扰结果。环境为 Apple M1 Pro、Chromium、ANGLE Metal,实际绘制尺寸 1440 × 900,1080p/60 fps 设置、固定晴天正午;从医院同一位置和方向开始,热身 2.5 秒后分别采集静止和按住前进的 300 帧。两个版本使用相同依赖及工作树,仅通过浏览器模块路由切回官方物理步进和旧合批实现。表内 CPU 是各渲染 pass 的提交时间,不包含整个游戏逻辑;CPU 与 GPU 可重叠,不能相加作为总帧时间。
| 场景与指标 | 优化前 | 优化后 |
|---|---|---|
| 固定视角渲染提交 CPU 中位数 | 5.6 ms | 2.8 ms |
| 固定视角渲染提交 CPU P95 | 6.3 ms | 3.7 ms |
| 固定视角帧间隔 P95 | 18.3 ms | 18.3 ms |
| 固定视角 GPU P95 | 8.11 ms | 8.01 ms |
| 连续骑行渲染提交 CPU 中位数 | 8.3 ms | 5.7 ms |
| 连续骑行帧间隔 P95 | 25.3 ms | 18.0 ms |
固定视角 draw calls 完全一致(中位 214、P95 270),CPU 余量增加但帧率仍受 60 fps 上限约束。骑行以相同输入采集固定帧数;旧路径耗时更长,因此终点及速度不同,这组数据用于说明该路线的实测表现,不能视为完全相同终点的逐帧对照或所有场景的固定提升比例。GPU 骑行 P95 约 15 ms,后续仍需优化 GPU 场景负载。
另在 390 × 844 手机视口检查页面、HUD 和触控控件,无横向溢出、错误遮罩或浏览器错误;静止/骑行帧间隔 P95 为 17.9/18.0 ms。它使用同一台 M1 Pro,不能代表实体手机性能。启动时间在两路径下约 6.3 秒,使用本地资源和已热身的 shader 缓存;本轮没有确认冷启动提升。
相关渲染及真实 WASM 单测共 7 文件、29 项通过;全仓类型检查、生产构建、原有性能预算、生产诊断代码排除检查(450 文件)与资源 Git 检查通过。17 项原生 GPU E2E 覆盖医院桌面/手机预算、公交碰撞、上下车、建筑及桥栏破坏、水面反射、浮点纹理回退、GPU 上下文恢复,以及地铁室内和广州塔各层真实碰撞。截图、CPU profile 和基准 JSON 为本地验证产物,不进入资源清单或 Git。
Browser 插件未提供,因此使用仓库已有 Playwright 与 playwright.gpu.config.ts。关键校验命令为 pnpm typecheck、pnpm build、pnpm verify:performance、pnpm verify:release、pnpm assets:git-check;渲染/物理单测使用 pnpm exec vitest run apps/dayun-kicker/src/render/staticBatch*.test.ts apps/dayun-kicker/src/render/staticDestruction.test.ts apps/dayun-kicker/src/physics/stepWorld.test.ts --maxWorkers=2。原生 GPU E2E 在外部本地服务器运行,结果目录设在 /tmp/dayun-performance,避免验证产物进入工作树。
后续架构方向
更大地图的长期路线是构建阶段按空间格预生成静态几何和语义数据,先加载出生点细节及全城简化轮廓,再加载周边细节;渲染、物理与导航分别管理范围。模型、贴图和生成文件沿用 COS 资源策略,保留破坏、LOD、水面捕获层和存档语义。街景当前第一轮合批参与水面层分类,不能直接删除来缩短构建时间。
初始启动 profile 还观察到首次 shader 使用约 7.6 秒。下一轮应对照 异步 shader 编译,按实际 HDR、世界、座舱及水面 pass 预热材质;提前编译并不保证总墙钟时间缩短,仍须验收真实首次可操作画面。本轮不新增资源、不迁移 WebGPU,也不据局部基准声称已经通过弱网冷启动或实体手机验收。
2026-10-10 街道布局预计算与局部灯光
生产构建现在运行原有确定性街道规划器,将接受的道路引用和少量作者放置保存为带内容哈希的结构化 JSON。运行时用同一浮点公式恢复,13,510 个街景实体与 34,920 段路缘的字段、顺序和负零朝向均与原结果一致;渲染、碰撞、破坏 ID 和存档继续使用同一布局。公交规划复用已有道路网络,避免再次构建相同图。
布局与独立解码分包由加载器和六份地图并发预取;使用格式版本、完整组合地图 SHA-256 与文件 SHA-256 校验。主入口为预取结果额外等待最多 100 ms,资源缺失、损坏、离线不可用、解码分包失败或迟到时回退原规划器。文件只由 Vite 写入 Web/desktop 构建输出,可随离线包分发,不在 Git 或媒体清单重复保存;没有新增外部媒体。这是布局预计算,还没有预生成完整几何或实现周边格流式加载。
单次 Node CPU 专项中,原规划 2,552.8 ms,JSON 解析与恢复 30.6 ms;编译工作转移到构建阶段。布局原始 1,220,183 字节,gzip 191,598 字节、Brotli 148,071 字节;直接保存完整坐标 JSON 则为 4,540,118 字节/gzip 1,035,373 字节。压缩量来自该专项,真实传输量以浏览器资源计时为准;不把局部 CPU 倍数当作启动或 FPS 倍数。
街景逐帧选两盏局部灯原来扫描 4,807 盏灯,现在查询与 30 m 光照范围相交的 80 m 空间格,复用结果数组;等距候选仍以原实体序号排序。白天强度为零时跳过查询,但保留两个 PointLight 对象,避免主题切换改变 shader 灯数。光斑实例只在显隐/破坏集合变化时重排并上传。随机候选、格边界、距离边界、等距顺序、破坏恢复、日夜切换及真实 PointLight 有效输出均与原算法对照。
| 街景 update 的纯 CPU 中位数(每轮 300 次、五轮) | 原实现 | 空间查询 |
|---|---|---|
| 白天 | 0.2228 ms | 0.0394 ms |
| 夜晚 | 0.2161 ms | 0.0392 ms |
该模块 CPU 耗时约减少 82%,不是整帧或 GPU 性能提升。下一阶段可继续处理 34,920 个路缘对象的构建与两级烘焙:专项中约占 342 ms 和 40.6 MiB 创建后堆占用,但迁移必须保留原格水面分类和破坏范围,目前未实现。
生产包启动对照
同机 Apple M1 Pro/Chromium/ANGLE Metal,390×844 触屏视口、DPR 2.75,固定晴天正午与自动/60 fps。旧生产包在改动前由预览服务器完整读入内存,保持本轮之前的刚体与合批优化;新旧各两个独立浏览器样本串行、禁用网络缓存,计时中没有 CPU profiler、其它 GPU 测试或重基准。先热身驱动 shader 缓存,因此不是全新驱动缓存的冷启动,也不是实体手机。
计时包括菜单 ready、点击开始及两次 RAF。弱网为 Fast 3G(1.6 Mbps 下载/750 Kbps 上传/150 ms RTT)与 4 倍 CPU 节流。
| 真实首次可操作时间 | 优化前两次 | 优化后两次 | 两次中位数变化 |
|---|---|---|---|
| 本地资源 | 6,329/6,334 ms | 4,650/4,523 ms | 6.33→4.59 s,约 −28% |
| Fast 3G+4× CPU | 27,900/27,811 ms | 22,904/22,536 ms | 27.86→22.72 s,约 −18% |
新包四次均命中 district:layout:precomputed,布局实际传输 148,071 字节 Brotli。district:maps 至 district:layout 的本地平均间隔由 1,878.5 ms 降至 55.5 ms,弱网/节流由 7,905 ms 降至 228.5 ms;这段也包含组合地图、道路图和校验,不是纯解码基准。额外下载抵消部分 CPU 收益,弱网场景构建仍约 12.8–13.1 秒,15 秒真实首帧门槛仍未通过。没有提高门槛或用更早的加载 mark 代替游戏画面。
地址、标题、playing 状态、画布、HUD、错误遮罩、页面错误和横向溢出均通过;手机视口截图已逐张检查。原始 JSON/PNG 保存在 /tmp/dayun-performance-layout/,不进入 Git。
验收与剩余门槛
最终相关单测 13 文件/60 项通过,包含完整布局与损坏数据、灯光参考算法、真实 WASM 步进、静态索引与破坏回归;全仓类型检查与生产构建通过。原有包体预算全部通过:首屏 JS 310.4 KiB gzip/350 KiB、CSS 15.8 KiB/16 KiB、街区入口 348.3 KiB/350 KiB,完整游戏资源 14.65 MiB/20 MiB。453 个 Web 发布文件校验通过,调试模块未打包;资源 Git 策略与 diff 检查通过。
原生 Metal 生产 E2E 4/4 通过:校验布局正常使用,以及缺失、内容损坏、请求一直等待时回退原规划器并进入 playing。标准 playwright.performance.config.ts 新增同一组生产回退用例并设为单 worker,防止启动计时与另一场景争用硬件;标准配置 4 通过、2 项启动预算失败。街区真实首帧 44,445 ms;首页按钮就绪 11,826 ms,但比赛真实首帧 27,193 ms,原 15,000 ms 断言保持。标准默认 headless Chromium 启动参数的独立诊断画布返回 SwiftShader/Vulkan;这不是上述 Metal 样本的 GPU 环境。
开发模式原生 GPU 定向 E2E 16/16 通过:公交桌面/触屏停靠与运动碰撞体、加载器与重试、真实炮击建筑与桥栏、水面反射裁剪/浮点降级/GPU 恢复与捕获预算,以及街道昼夜预算和花池碰撞。1440×900 桌面与 390×844 触屏画面已检查,HUD 和场景正常;与上述生产 4 项合计 20 项原生 GPU 回归通过。地图/主模块故障注入的启动错误日志及浮点降级警告属于预期场景,恢复后检查通过。命令为 PLAYWRIGHT_BASE_URL=<开发地址> pnpm exec playwright test e2e/district-loading.spec.ts e2e/bus-transit.spec.ts e2e/tank-combat.spec.ts e2e/water-rendering.spec.ts --config playwright.gpu.config.ts,另运行 e2e/district.spec.ts --grep 'keeps street lighting within budget|renders polished night streets'。验证服务器均关闭 HMR/文件监听,串行运行。
没有执行完整 release:check、重新打包桌面客户端、跨平台 WebGPU 或实体手机持续测试。浏览器插件未提供,使用仓库已有 Playwright。关键命令:pnpm typecheck、pnpm build、pnpm verify:performance、pnpm verify:release、pnpm assets:git-check;生产回退使用 PRECOMPUTED_LAYOUT_E2E=1 PLAYWRIGHT_BASE_URL=<生产预览地址> pnpm exec playwright test e2e/precomputed-layout.spec.ts --config playwright.gpu.config.ts,标准预算使用 pnpm test:performance。结果、截图和 trace 位于 /tmp/dayun-performance-layout/。
2026-10-10 WebGPU 迁移前原型基线
用户选择先完成主线性能优化,再以独立原型验证 WebGPU。本轮使用实际安装的 Three 0.186.1、仓库已有 Playwright 与 TypeScript,显式执行 requestAdapter、requestDevice,取得 GPUCanvasContext,等待 renderer.init(),并要求 renderer.backend.isWebGPUBackend === true。本机返回 Apple metal-3、isFallbackAdapter=false,实际后端为 WebGPUBackend,启用了 timestamp-query;设备与页面错误均为零。这份迁移前记录没有把 WebGL 回退计作 WebGPU;当时尚未提供生产开关。现有开关和迁移后的验证见下一节。
第一轮原型将当时的静态合批与原始网格在同一标准材质场景逐像素对照,覆盖主视角、镜像相机视角、正交相机、真实方向光阴影、破坏/恢复及共享祖先隐藏/恢复。21 项中 14 项通过,7 项 FrontSide+阴影失败;无阴影的 7 项完全一致,DoubleSide+阴影的 7 项通过(镜像视角仅 1 像素差值大于 2)。FrontSide+阴影主视角有 22,707/65,536 像素差值大于 2,平均 RGB 绝对差 26.87,图像侧面丢失。实测回调显示,主画面选择索引后,嵌套阴影的 onBeforeShadow/onBeforeRender 再改写同一索引,主画面随后使用阴影视角的内容;阴影 onBeforeRender 接收的原始 FrontSide 材质也不能代表最终 override material 的有效 side。迁移需要独立的 pass 索引资源和回调适配,不能用改成 DoubleSide 掩盖差异。镜像相机测试没有实现或验收游戏水面。
上传计数来自真实 GPUQueue.writeBuffer,静态索引的实际绘制前缀同时通过 GPU buffer 回读,全部与 CPU 索引一致。每组 60 帧的结果如下;两种 usage 在破坏与恢复时均各产生一次必要上传。
| 上传场景 | DynamicDrawUsage | 以 version 更新的 StreamDrawUsage |
|---|---|---|
| 静止静态合批索引 | 0 次/0 字节 | 0 次/0 字节 |
| 移动相机,索引 version 变化 4 次 | 4 次/135,648 字节 | 4 次/135,648 字节 |
| 材质每帧变化,索引 version 不变 | 60 次/2,211,840 字节 | 0 次/0 字节 |
| 静止实例矩阵 | 60 次/245,760 字节 | 0 次/0 字节 |
| 实例矩阵每 6 帧变化,version 变化 10 次 | 60 次/245,760 字节 | 10 次/40,960 字节 |
该版本的 NodeMaterialObserver 会跳过无需几何更新的静态帧;DynamicDrawUsage 的重复上传发生在完整刷新等路径,不能概括成所有静态索引每帧都上传。实例动态属性、自定义 node、材质变化与多 pass 应分别测量。独立 256 盒子、256×256、DoubleSide、无阴影模型的提交 CPU 中位数约 0.4–0.5 ms、GPU timestamp 中位数约 0.104–0.115 ms;usage 间的计时波动不足以证明稳定加速。本轮没有游戏级 WebGL/WebGPU A/B,也不将模型耗时换算成游戏性能提升。
材质实测同样阻止直接替换后端:onBeforeCompile 与 material.onBeforeRender 均未调用,object.onBeforeRender 有调用;ShaderMaterial 输出黑色并报告不兼容;旧 Reflector 渲染时报 buffers 未定义。按 Three WebGPURenderer 迁移说明,现有 GLSL、onBeforeCompile 定制、呈现与水面反射/折射需要迁移为 node/TSL,并保留原有深度坐标、折射厚度和捕获调度。
下一阶段开放用户切换前,必须完成上述材质与多 pass 视觉等价;建立所有游戏入口及预览的一致异步 renderer 初始化,分别显示用户选择与实际后端、提供明确的不可用/回退原因;保存当前进度并安全重建画布与 GPU 资源,按 Renderer 生命周期接口处理设备丢失与恢复;最后在相同场景、画质、分辨率和目标设备上比较 WebGL/WebGPU 的启动、CPU/GPU、帧间隔 P95 及资源使用,再决定默认后端。
复现脚本保存在 scripts/performance/webgpu-prototype/,没有接入游戏入口或 bundle。先在一个终端启动本地服务器,再在另一个终端运行:
pnpm --filter @yunlefun/dayun-kicker exec vite --host 127.0.0.1 --port 43175 --strictPort
node scripts/performance/webgpu-prototype/run.cjs脚本通过同源模块路由加载当前仓库源码,不安装新依赖;默认从脚本位置确定仓库根,DAYUN_ORIGIN 可指定服务器,DAYUN_WEBGPU_OUTPUT 可指定输出目录(默认 /tmp/dayun-performance-webgpu,自动创建)。--enable-unsafe-webgpu 是本机实验的 Chromium 启动配置,不代表普通用户环境已可用;Metal 启动参数只在 macOS 使用,其他平台仍须核实实际 adapter 与 backend。完整环境、源码 SHA-256、回调、逐用例差异和上传计数见本地结果 JSON(本地证据在仓库外保管)与本地技术报告(本地性能报告由维护者在仓库外保管)。PNG/JSON 为本地产物,不进入生产资源或 Git;换设备应重新运行,status: complete 只表示检测结束,兼容结果以各用例和 summary 为准。
自动选择与用户切换 WebGL/WebGPU
画面设置现在提供「自动(按设备选择)/WebGL/WebGPU」,沿用 dayun-kicker.display.v1。旧设置自动补齐 renderer: "auto"。实际状态由主场景发布,车库预览不覆盖该状态;更改选项先保存,点击「保存并重新载入」后生效。分辨率与帧率仍即时更新。重新载入会重新进入场景并结束当前比赛或联机;街区先保存自动进度,桌面端再等待磁盘确认。捕获失败、存档受保护、磁盘失败或 10 秒超时都会保留页面并允许重试。
| 选择 | 实际启动行为 |
|---|---|
| 自动 | 检查 WebGPU API,取得实际 adapter 和 device,初始化真正的 WebGPUBackend;成功后使用 WebGPU |
| WebGL | 直接启动现有 WebGLRenderer,不请求 adapter 或下载 GPU 运行时 |
| WebGPU | 尝试相同的真实 GPU 初始化,保留用户偏好;不支持或失败时使用 WebGL,并显示原因 |
adapter 不可用时不会下载 WebGPU 包。WebGPU adapter、device 和运行时初始化尝试最多 8 秒,超时晚到的设备、画布和渲染器会清理;这不代表整个场景的首次可玩时间上限。Three 内部 WebGL fallback 不计作 WebGPU,统一重新构造原 WebGLRenderer。能力检查选择可运行的后端,没有同时启动两套完整场景测试谁更快。WebGPU 并不保证每台设备、每个视角都获得更高帧率;遇到性能差异可手动选择 WebGL。
WebGPU device 丢失时暂停输入和音频,保存街区进度并确认落盘;保存及恢复标记写入成功后,重新加载为一次 WebGL 恢复启动,失败时留在页面提示重试。用户原偏好不被覆盖。WebGL context 恢复继续沿用原地恢复流程。开发诊断显示真实 drawCalls,GPU 模式跳过依赖 WebGL 私有接口的计时器。
兼容迁移包含 TSL 天空与远平面云层、地面材质、总部 atlas、玻璃、广州塔局部雾、交通接触阴影,以及 HDR 呈现、水面和后视镜。水面继续按高度共享、按距离和频率捕获,使用 WebGPU 的深度区间、纹理 Y 方向和真实斜切逆投影保留水下厚度吸收。HDR 保留原高光、饱和度和暗角;WebGPU 使用其支持的 4x MSAA。普通 Three PBR 材质仍由后端转换,现有 WebGL shader hook 保留。实现遵循 Three 的 WebGPU/TSL 迁移说明,没有修改私有 NodeLibrary 或伪装渲染器类型。
静态合批的 GPU 主画面、阴影、反射各自保留独立索引,顶点数据共享,嵌套 pass 后恢复父 geometry;最终阴影 side 与实际 override 一致。每个 view 缓存相机、变换、祖先可见性和破坏状态,静止主画面/阴影连续 20 帧索引 version 不变。动态阴影冻结使用一次注册的灯集合,新增/移除子树和之后开启 castShadow 都会维护注册,不在每个次级 pass 遍历整座城市。
原型的 21 组真实 GPU 图像复测全部通过,原来失败的 7 组 FrontSide 阴影已修复。重现可运行 DAYUN_WEBGPU_VISUAL_ONLY=1 DAYUN_WEBGPU_OUTPUT=/tmp/dayun-performance-webgpu-switch node scripts/performance/webgpu-prototype/run.cjs;此原型只激活标准材质合批协议,完整材质和水面由游戏 E2E 验证。历史上传和微基准数字属于迁移前实现,不作为新版游戏加速结论。
新增 e2e/render-backends.spec.ts 与 e2e/render-backend-settings.spec.ts 覆盖真实 WebGL→WebGPU→自动切换、偏好和实际状态分离、保存失败不重载、两种 GPU 偏好在 API 缺失时回退、实际反射/水下捕获与遮挡恢复、完整街区运行,以及 device 丢失后存档坐标和一次 WebGL 回退。本机 Chromium/Metal 无需 --enable-unsafe-webgpu 即可运行游戏,桌面 1280×720 与手机视口 390×844 已检查,页面标题、画面、设置交互、溢出、运行时错误和截图均通过。实体手机、其他 GPU、Safari/Firefox 和重新打包的桌面客户端仍需各自验证。浏览器插件未提供,本轮使用仓库 Playwright,证据保存在 /tmp/dayun-webgpu-e2e/。
最终验证与发布体积
全仓单测 222 文件/1,403 项通过,全仓类型检查与生产构建通过。新增后端用例 7/7 通过,车库、设置、双人合作与四人城市合作的原生 GPU 回归 7/7 通过;两份新增 E2E 已加入常规 test:e2e 命令。另对生产构建执行 5/5 启动检查:首页 WebGL、首页自动 WebGPU、完整街区 WebGPU、完整街区 WebGL,以及 GPU API 不可用时的手动偏好回退,实际后端、设置状态、画布和页面错误均通过。
原性能体积预算保持不变并全部通过:首屏 JS 309.6/350 KiB gzip、CSS 15.8/16 KiB、街区入口 347.8/350 KiB、城市合作入口 348.7/350 KiB,完整资源 15.48/20 MiB。verify:release 校验 468 个 Web 发布文件,生产诊断排除、assets:git-check 与 diff 检查通过。WebGL 静态依赖链不包含 GPU 运行时,生产 WebGL 与无 adapter 回退样本的 GPU 资源请求数为零;真正启用 WebGPU 时会额外下载其按需分包,其中 three-webgpu 为约 192.5 KiB gzip,还包含 node 材质等模块。
为复用同一组 Three 核心类并保持 WebGL 预算,构建精确解析已安装 Three 0.186.1 的源码入口,GPU 专用模块留在动态依赖链;生产 GLSL 只去除注释、空行和行首尾空白,保留 token、预处理行边界及 hook 匹配。相关测试逐一检查安装包 shader;升级 Three 时需要重验源码入口、shader 格式、两套实际画面与分包闭包,不可仅根据构建成功判断兼容。
同一最终生产包的标准弱网/4× CPU 配置仍为 4 项布局回退通过、2 项启动预算失败:街区真实首帧 42,971 ms;首页按钮就绪 11,991 ms,比赛真实首帧 27,520 ms,原门槛均为 15,000 ms。本轮没有降低画质、提高门槛或提前替换首帧计时点。这些结果不能证明 WebGPU 比 WebGL 更快;自动模式依据可用能力选择,仍需要目标硬件的同场景性能对照。日志、截图和 trace 在 /tmp/dayun-webgpu-performance/,生产后端检查记录在 /tmp/dayun-prod-backends.log。完整 release:check 和所有平台测试尚未执行。
启动门禁按场景区分
2026-10-10 提交前复测再次触发原 15 秒断言:首页按钮就绪 12,019 ms,比赛真实首帧 27,777 ms,完整街区真实首帧 44,151 ms。已获得维护者授权,按首页、比赛和完整城市区分回归预算;此前段落记录原门槛下的历史结果,以本节为当前规则。
Google 当前 Web Vitals 指南 的良好体验门槛包含 LCP ≤ 2.5 秒、INP ≤ 200 ms,按真实用户第 75 百分位验收;这些指标与完整游戏首次可操作时间不同。较早的 RAIL 为普通网页慢速移动网络首次交互提出约 5 秒目标,并建议只加载最少初始内容、延后其他工作;它也不能推导出完整 3D 城市必须在同一时间内全部加载。Unity Web 渐进加载指南 建议轻量初始场景、按需资源和异步场景切换,没有给完整游戏指定统一 15 秒上限。下列数字来自本项目实测和 CI 余量,不是业界标准;首页体验仍需继续优化,放宽场景回归上限不代表解决了长等待。
| 从导航开始计时的阶段 | 当前上限 | 范围 |
|---|---|---|
| 首页按钮可操作 | 15,000 ms | 保留现有首页门槛 |
| 比赛真实首帧 | 35,000 ms | 包含点击开始、比赛按需分包、首次 shader 和两次 RAF |
| 完整街区真实首帧 | 60,000 ms | 包含地图、布局恢复、场景与物理构建、首次 shader、点击进入 playing 和两次 RAF |
统一条件保留 Pixel 5 视口、Fast 3G(1.6 Mbps 下行/750 Kbps 上行/150 ms RTT)、禁用网络缓存、4 倍 CPU 降速和标准 headless Chromium。当前本机诊断得到 ANGLE / Vulkan / SwiftShader 软件渲染,不是实体手机 GPU;计时附件记录浏览器版本与实际 GL renderer,不能与原生 Metal/WebGPU 的数字混为同一组样本。相同条件的两次独立街区诊断为 43,242 ms / 43,036 ms:场景构建长任务约 12.3 / 12.5 秒,首次渲染所在长任务约 16.4 / 16.3 秒;CPU profile 在后者约 15.8 秒处于原生程序工作,Three 程序首次使用的堆栈也有采样。这支持继续调查场景分阶段构建和异步 shader 准备,不足以声称全部等待由某个单一函数导致。
两次诊断中 district:first-frame 在约 23 秒已经写入,但后续原生工作与真实点击仍未结束,因此保留点击后的真实计时点。比赛诊断在同一浏览器的热 shader 缓存下约 13.2–13.4 秒,不能取代上述独立冷启动失败样本。首屏/入口 JS、CSS、总资源、绘制 calls/triangles、媒体 Git 策略及故障回退断言均未放宽,也没有降低渲染质量。
调整后的标准生产性能套件 6/6 通过:首页 11,918/15,000 ms、比赛 27,133/35,000 ms、完整街区 45,294/60,000 ms,另包含布局正常使用及缺失、损坏、迟到的完整回退验证。命令为 pnpm exec playwright test --config playwright.performance.config.ts --output /tmp/dayun-fixed-performance,日志为 /tmp/dayun-fixed-performance.log。
扩展浏览器检查还发现手机音频控件用例在街区未完成加载时就查找开始按钮,误用 15 秒控件等待作为整场景启动限制。用例现在先等待 ready,再以原有控件断言检查可达性、音轨选择和溢出,独立生产启动门禁仍约束加载时间。原失败在相同标准软件渲染环境下定向复测 1/1 通过(42.2 秒),日志为 /tmp/dayun-fixed-audio.log。完整 262 项套件在发现该问题后中止以隔离复现,已通过 7 项,另有 1 项被中断、253 项未执行;修复后没有重跑完整套件,不声称完整 release:check 已通过。
同一代码的全仓类型检查、222 文件/1,403 项单测、Web 与桌面渲染构建及其原有体积/发布校验均通过,原生 GPU 定向回归 16/16 通过,覆盖后端降级、设置切换、设备中断存档、水面与真实合作客户端。暂存区 1,355 个文件的资源策略和 diff 检查通过;没有新增媒体。实体手机持续表现、完整桌面应用打包和跨平台性能仍需分别验收。
城市合作碰撞边界预筛(ba9132f 后续补丁)
城市僵尸每次路径判断保持原有 0.3 米采样间隔,但一个水域轮廓可能有数百条边。原实现对桶内每个轮廓调用完整点内判断,并对远离采样点的所有边反复求精确线段距离。新增按不可变轮廓弱引用缓存的整体/逐边 AABB,仅剔除不可能接触的候选;保留原有点内、精确距离、半径、桥面、水洞和滑动规则。边界筛选加入保守浮点余量,不缓存或舍入查询点。普通陆地道路判断找到一个支持路段即停止,只有水域阻挡时才再查桥面。
复现命令(仓库根目录,无需浏览器或图形参数):
node packages/dayun-kicker-coop/scripts/benchmark-city-collision.mjs
pnpm exec vitest run packages/dayun-kicker-coop/src/cityWorld.performance.test.ts基准在 Linux / Node 24.19.0 上,对冻结于 ba9132f63380adb1d1ffb1c14512fd685a0838a4 的原实现与新实现使用相同六源完整地图(6,768路段、1,150建筑、17水域)、seed 713。每项预热一次、计时五轮,交替前后顺序并取中位数;源码转换和地图加载不计入热路径计时。先逐项校验85,580个查询与300个完整权威快照,包含位置、事件、生命、波次等状态,完全一致后才输出计时。
| CPU工作负载 | 原实现中位数 | 优化后中位数 |
|---|---|---|
| 85,580次步行判定 | 171.48ms | 57.58ms |
| 4人、32僵尸、300tick权威模拟 | 6,618.24ms | 1,279.53ms |
| 冷world构建 | 13.69ms | 14.09ms |
| 冷缓存首遍查询 | 161.28ms | 68.58ms |
独立计数运行中,两版步行查询数均为559,977,精确线段距离调用从140,596,468降至850,921(约减少99.39%)。计数器不参与上述正式耗时样本。模拟结束仍为running且有32只僵尸,未用提前结束减少工作量。
缓存有内存代价:该模拟按需准备3个轮廓/254条边;覆盖全部查询后准备1,163轮廓/7,214边,共15,591个普通对象及1,163个边数组。该数字是对象计数,不是堆字节测量;WeakMap不额外延长原轮廓生命周期。地图几何沿用原有网格索引的不可变前提。
这些是局部CPU微基准,不能换算成浏览器FPS、GPU加速比、多人网络性能或完整启动时间。本轮不改变画质、渲染后端或启动预算,没有重新开启临时SwiftShader测试。实际城市渲染、相机轨迹、动画和联网体验仍需要单独的目标设备验收。
2026-10-12 转动视角优化与性能读数
本轮覆盖街区、城市合作及 macOS 桌面渲染路径。代码验证完成后,按用户继续指令在负载回落的窗口串行执行正式 A/B。出生点首次转视角和城市联机的长帧明显减少,macOS 尾帧改善;持续 CPU 收益因环境而异,不能概括为全面提速。下方“诊断样本”表属于较早的受污染数据,正式结果见本节后半部分。
静态合批按相机缓存面朝向判断,只有透视视点位移/正交视向变化小于所有相关面平面的安全余量才复用;透视相机纯旋转不改变面朝向,但视锥仍需更新。跨过边界、材质 side 变化、镜像/正交视角和破坏状态变化仍执行原判断。视锥、可见性及必要索引上传继续生效,参考算法测试逐面比对结果。没有降低几何细节、阴影、水面效果、实际缓冲分辨率或物理频率。
WebGPU 在加载期间用实际场景、相机和呈现目标预热四个朝向,并执行对应世界、阴影和水面 pass。加载时保持主循环暂停,结束后恢复相机与临时可见性,预热帧不计入性能面板。这能提前准备出生点周围的管线,进入新区域仍可能产生新的编译。代价是更长的加载时间:当前受负载影响的浏览器预热为 3.33–16.62 秒,原生冷启动样本为 3.67 秒;不能把较早的首次绘制 mark 当作可操作时间。显示帧率限制器允许小范围回调抖动,同时保留累计截止时间与帧率上限,避免高刷新率回调因微小提前而漏掉目标帧。
正式版在画面设置或 F8 开启轻量面板,显示实际 FPS、帧耗时 P95/P99、超过 50 ms 的帧数、渲染提交 CPU、绘制数、三角形、实际缓冲尺寸和后端。关闭后停止采样;GPU 查询与完整分析仍只在开发模式手动开启。网络 HUD 显示连接、同步停滞和断线;RTT 来自确认回包,过期或不支持时显示不可用,展开可看快照年龄与同步频率。Steam 房主和本地挑战分别标明身份,旧云端竞速 SDK 没有 RTT 探针时不伪造延迟。界面及计量边界见 UI 组件约定。
诊断样本与验收状态
设备为 M1 Pro/Metal,浏览器 Chromium 156,原生测试运行 Electron 44.7。窗口 1440×900;浏览器 DPR 1、实际缓冲 1440×900,原生 DPR 2 在 1080p 像素预算下为 1821×1138。固定 60 FPS、午间光照和同一相机拖动轨迹;联机使用真实开发服务器与两个独立客户端,采样开始和结束均要求对局仍为 running。原始数据和截图只在本地保存。
测试期间存在其他构建、浏览器任务和较高交换内存占用,前后系统负载不一致。所有数字属于受污染的诊断样本。表中的 P99 是各轮 P99 的中位数,长帧数是各轮合计。
| 场景 | 采样 | P99 前→后 | 超过 50 ms 前→后 | 实际 FPS 中位数前→后 |
|---|---|---|---|---|
| 浏览器 WebGPU,出生点首次转视角 | 三组各 15 秒,新进程 | 27.5→33.8 ms | 15→0 | 58.34→57.43 |
| 城市联机 WebGPU,正常冲刺并转视角 | 三组各 10 秒,新房间 | 79.6→19.5 ms | 15→0 | 45.93→59.92 |
| macOS WebGPU,出生点首次转视角 | 一组各 15 秒,新进程 | 30.2→20.5 ms | 5→0 | 57.87→59.99 |
| 浏览器 WebGL,已加载街区持续转视角 | 三轮各 60 秒 | 18.6→18.8 ms | 1→2 | 59.98→59.85 |
| 浏览器 WebGPU,已加载街区持续转视角 | 三轮各 60 秒 | 18.6→18.1 ms | 0→1 | 59.98→59.94 |
| macOS WebGPU,已加载街区持续转视角 | 三轮各 30 秒 | 18.8→25.5 ms | 1→2 | 59.96→59.93 |
首次转视角样本中的长帧减少,但浏览器冷样本 P99 与原生持续样本 P99 未改善。原生冷样本的就绪时间为 18.24→23.25 秒,浏览器冷样本就绪时间中位数为 18.10→21.78 秒。管线预热把部分成本移到加载期;需要同时验收加载时间与游玩长帧。上述结果不能宣称持续性能全面提升,也不能代表 Safari、其他 GPU、实体手机或真实 Steam/云端 WAN。
宽范围转视角的绘制峰值约 389 次/12.8 万三角形,前后基本一致,但超过历史局部地图 300 次/9 万三角形的目标;现有体积预算保持,场景目标仍待进一步处理。朝向缓存和预热也有内存成本,当前样本没有证明堆内存减少。
采集器的 formatVersion: 2 将 CPU 指标修正为一次实际世界渲染函数的墙钟时间,包含嵌套阴影/水面提交,排除逻辑更新及最终呈现。较早版本逐个累计渲染调用,会重复计算嵌套 pass;旧 CPU 数字不能与新版面板直接比较。CPU profile/trace/--pacing=true 回调记录仅用于定位,不混入正式帧耗时验收。
稳定窗口的首组对比发现限帧回归:浏览器回调仍规律到达,30 秒 1,801 次回调却被限帧器拒绝 35 次。加载暂停后保留的旧相位与回调量化落在容差边界;容差还被错误算作已过期时间,会多推进一个截止时间。现已在长暂停后重新对齐,并将提前容差与过期计数分离。两项针对真实时序特征的回归测试先复现失败,再通过修复。修复后独立 60 秒记录 3,600 帧、P99 18.5 ms、超过 50 ms 的帧为零;仍需与完整重复矩阵一起评估。
复测时串行运行,保持同一设备、后端、实际缓冲尺寸、时间、场景、路径和系统负载,并记录就绪时间及 P95/P99、长帧、绘制量、内存与错误。使用目标开始前冻结的私有源码副本作为 --baseline,不复制源码或原始日志到公开文档仓库。
pnpm benchmark:camera --platform=browser --backend=webgpu --scenario=district --duration=60000 --rounds=3 --output=/tmp/gza-camera-current
pnpm benchmark:camera --platform=desktop --backend=webgl --scenario=district --duration=30000 --rounds=3 --output=/tmp/gza-camera-desktop
pnpm benchmark:camera --platform=browser --backend=webgpu --scenario=city --duration=10000 --rounds=1 --output=/tmp/gza-camera-city出生点首次转视角另加 --cold=true --position=spawn;冷启动与联机新房间都使用三次独立命令、每次 --rounds=1。单命令 --rounds=3 会复用同一进程/房间,不构成三个独立冷样本;新进程也不保证 GPU 驱动缓存清空。联机长时间验收应控制正常移动路径并保持对局存活,提前结束的样本拒绝用于比较。完整冻结基线与 --baseline 的应用源码替换范围见复测手册。
代码与功能验证
最终全仓类型检查通过。单 worker 的完整单测运行 295 文件/1,878 项全部通过,包含两项先复现限帧失败、再通过修复的回归,以及网络停滞恢复后的频率窗口。早期并发运行的地图集成超时记录保留,没有扩大超时阈值。
Web 和 desktop 构建、原有包体预算、各 535 个发布文件检查均通过。Web 首屏为 313.6 KiB gzip/350 KiB,CSS 15.9 KiB/16 KiB,完整资源 19.43 MiB/20 MiB;没有提高预算。轻量面板进入正式包,完整开发分析被排除。资源 Git 策略、文档引用/类型和 diff 检查通过。
浏览器原生 GPU 定向回归覆盖转视角与车辆朝向、面板开关及桌面/390 像素布局、WebGPU 手动 CPU/GPU 捕获后恢复,以及真实开发服务器上的 RTT、快照停滞和断线显示,4 个用例通过;最后修改涉及的面板/GPU/网络 3 项重新通过。捕获之后没有 GPU 查询或渲染 pass 验证错误。快照加载或停滞后重新建立频率窗口,恢复后不会把加载空档算入近期同步 Hz。最终截图已检查,网络展开按内容收窄,性能读数使用共享强底色和诊断层级。
原生 macOS 的最终正式构建代码 E2E 1 项通过,覆盖 F8、偏好落盘与重载、三个网络 IPC 无采样时返回不可用、本地挑战的轻量面板与本地状态、无完整开发分析及运行时错误。此运行实际使用 WebGL;街区就绪 9.59 秒,本地挑战 10.51 秒,只是功能验证记录,不能与上述 WebGPU 开发模式原生 harness 的启动数字比较。没有重新生成签名 DMG 或完成实际 Steam 账号/云端公网联机。
现有原生指针捕获自动化仍报 WrongDocumentError;浏览器拖动视角和原生 harness 的实际相机转动已验证,不能据此宣称原生指针捕获 E2E 全部通过。标准节流启动性能 suite 与完整 release:check 没有在本轮重新执行。跨设备画面及公网联机验收仍未覆盖。
稳定窗口的本机 A/B
以下采用修正后的 formatVersion: 2,不启用 profiler、trace 或 pacing 记录。窗口、后端、实际缓冲尺寸、60 FPS 上限、午间场景与相机拖动保持一致。浏览器为 Chromium 156/Metal,macOS 为 Electron 44.7/ANGLE Metal 的原生窗口 harness,后者与生产包装/IPC 功能验证分开。WebGPU 浏览器缓冲为 1440×900,macOS WebGL 为 1821×1138。未发现其他构建或浏览器测试;各用例记录系统负载和交换内存,负载约 3–5、交换内存约 7.8 GB,属于本机日常环境,不代表裸机实验。
基线来自目标开始前冻结的源码副本。WebGPU 持续样本与首次转视角/联机样本交替前后顺序;macOS 对初次 CPU 异常另做反向顺序复测。前后均要求实际后端正确、相机确实转动、街区为 playing/联机为 running,运行时错误为零。表中的 P95/P99 和渲染 CPU 是各轮统计值的中位数,六轮时取中间两项平均;长帧为各轮合计。
| 场景 | 每版采样 | P95 前→后 | P99 前→后 | 超过 50 ms 前→后 | 渲染提交 CPU P50 前→后 |
|---|---|---|---|---|---|
| 浏览器 WebGPU,已加载街区转视角 | 三轮各 60 秒 | 17.5→18.1 ms | 18.4→18.5 ms | 0→0 | 7.4→7.6 ms |
| 浏览器 WebGL,已加载街区转视角 | 三轮各 30 秒 | 18.0→17.6 ms | 18.5→18.3 ms | 0→0 | 6.9→6.2 ms |
| macOS WebGL,已加载街区转视角 | 六轮各 30 秒,含反向复测 | 22.35→18.8 ms | 26.25→20.05 ms | 0→0 | 6.0→6.45 ms |
| 两个真实城市联机客户端,冲刺并转视角 | 三组各 10 秒、新房间 | 17.8→18.2 ms | 32.6→18.3 ms | 7→0 | 7.4→7.5 ms |
| 浏览器 WebGPU,出生点首次转视角 | 三组各 15 秒、新进程 | 17.2→18.3 ms | 31.6→18.6 ms | 8→0 | 7.5→7.8 ms |
持续街区前后实际 FPS 都约 60,城市联机中位数为 58.93→59.91,出生点首次转视角为 58.63→60.00。首次转视角 P99 约降低 41%,城市联机 P99 约降低 44%;两类样本的超过 50 ms 长帧合计 15→0。持续 WebGPU 没有稳定加速;WebGL 浏览器渲染提交中位数约减少 10%,不能把这换算成同幅度的 FPS 提升。
macOS 的帧耗时 P99 中位数约减少 24%,但优化版各轮 P99 仍为 19.9–25.8 ms,未完全消除尾帧。CPU 初次一组为 6.2→6.9 ms,反向复测为 5.8→6.0 ms;整体提交墙钟中位数为 6.0→6.45 ms,本轮不主张 macOS CPU 加速。单独的 CPU profiler 将裁剪函数采样时间从约 1,884→1,341 ms/10 秒,仅用于确认热点工作减少,不替代未启用 profiler 的游戏级结果。
代价同样计入记录:出生点真实就绪时间中位数为 13.93→16.58 秒,双客户端页面加载、建房/加入、准备和启动流程耗时为 11.80→15.23 秒。后者结束于点击开始后、确认 running 前,不是单客户端或首个可操作帧的精确加载时间。WebGPU 四视角及多 pass 预热约 2.55–2.69 秒;WebGL 跳过该预热。预热把首次游玩中的编译成本移至加载期,不能当作免费收益。保留画质、阴影、水面、MSAA、像素预算与物理频率;街区宽范围绘制峰值前后约 390 次/12.9 万三角形,没有以降低绘制质量取得上述长帧结果,也没有宣称堆内存减少。
城市客户端实际 RTT 样本约 1.6–3.3 ms,连接状态正常;这是本地开发服务器,不是公网延迟。Windows、Safari/Firefox、实体手机、macOS 生产 WebGPU 后端、实际 Steam/云端 WAN 和未经过的新区域仍需各自验证。以上是指定本机、路径与版本上的验收,不能承诺任意视角和负载下均无卡顿。
2026-10-12 第二轮:残余尾帧、加载预热与卡通氛围
这一轮以第一轮完成后的版本重新冻结基线,优先处理 macOS 持续转视角仍出现的约 25 ms 尾帧,再缩短 WebGPU 预热。维护者同时明确选择更明显的卡通色块、轮廓感和夸张动画;主矩阵 A/B 包含主矩阵画面版本,没有沿用仅性能补丁的采样结果。美术来源、调节参数与动画所有权见卡通画面氛围指南。
指定本机与路径的正式矩阵已完成:macOS P99 中位数 25.8→19.8 ms,90 秒采样内超过 22 ms 的帧 552→0;出生点 WebGPU 预热中位数 2,460.7→404.0 ms,真实就绪时间 16.006→13.919 秒,同时保留首次转视角的长帧结果。持续 WebGPU 的渲染提交 CPU 中位数增加约 4.3%,因此本轮同时报告主矩阵画面版本的代价。
改动与正确性边界
- 原生回调记录将残余尾帧定位到接近目标期限的提前回调被拒绝。限帧准入允许至多 2 ms 的提前余量,并用重复回调保护避免同一周期重复提交;余量不计入已过期截止时间的推进。高刷新率、时间量化、长暂停和重复回调均保留回归,帧率上限与物理规则不变。
- WebGPU 四朝向改用实际绘制准备所需管线,删除重复的显式编译与额外准备工作;阶段间让出主线程,保留真实 HDR target、世界、阴影和水面。准备前同步实际 target 尺寸,完成/失败时恢复相机、临时可见性、原水面状态和采样状态。首次加载之后重新对齐游戏时钟,不把加载空档累计为游玩更新。
- 街区现有 HDR resolve 复用中心与八个邻域样本做局部色块与颜色反差墨线。它不是深度/法线剪影轮廓。光色、材质细节、阴影、水面、既有 MSAA、实际缓冲尺寸和物理行为保持各自职责,没有下调质量设置或放宽预算。
- 本地步行骑手增加有上限的躯干弹性与头部跟随,保持根位置、根朝向、腿与脚原运动;减少动态效果和暂停/瞬移时复位。真实 cockpit 与烘焙世界模型均有资源共享/可见性回归,后者检测不到独立脸部时不单独移动头盔。
- 独立城市联机页面新增自有 HDR target 与最后的呈现工作;嵌入街区的挑战借用已有 resolve。共享与自有对象分别恢复/释放,HDR 不支持时保留直接绘制。新增城市呈现有显存与 GPU 成本,本轮未独立测量其显存字节,不能以 JS heap 推断 GPU 内存收益。
正式 A/B 的条件与结果
设备为 Apple M1 Pro/Metal。浏览器 Chromium 156.0.8078.4,窗口与实际缓冲 1440×900、DPR 1;原生为 Electron 44.7.0/Chromium 152 的 WebGL 窗口 harness,1440×900、DPR 2,1080p 像素预算下实际缓冲 1821×1138。主客户端固定 60 FPS、相同正午光照、场景位置与真实相机输入轨迹,HDR 使用原有 4x MSAA。基线与主矩阵画面版本的缓冲尺寸保持一致。
每个进程前后记录系统状态,44 条记录中的一分钟负载为 3.19–11.26,交换内存占用为 8,557.75–8,565.75 MB(约 8.56 GB)。这是有非零日常负载的本机环境,不是干净裸机实验。应用源码按这次矩阵精确冻结,并核验共享包源码、依赖 lock 与资源清单一致。期间原生 SDK 生成的 addon 有重新构建,但渲染器 harness 不加载该 addon,相关重建与生产包装功能检查不混入帧耗时样本。
正式样本串行运行,关闭 profiler、trace、pacing、完整 GPU 分析与轻量读数面板,不与构建或浏览器功能测试重叠。macOS、首次转视角和新联机房间采用三次独立样本,顺序为前/后、后/前、前/后。持续浏览器每版在同一进程内测三轮:WebGL 先基线后主矩阵画面版本,WebGPU 先主矩阵画面版本后基线;不能把这两项说成每轮都交替。所有采样要求实际后端正确、相机确实旋转、街区 playing/联机 running、有效帧与 CPU 样本非空,运行时错误为零。
回调时间线与管线 warm profile 属于定位诊断,不混入下方正式结果。开始改动前记录的验收门槛与本组结果如下:
| 条件 | 预先约定的门槛 | 矩阵结果 |
|---|---|---|
| 原生持续转视角 | P99 中位数 ≤20.5 ms,P95 ≤19 ms;超过 22 ms 的发生率至少减少 50%;实际 FPS ≥59.5 | 19.8 / 18.8 ms;552→0;各轮 FPS 59.964–59.984 |
| 浏览器与联机回归 | 同条件 P99 允许变化不超过 +1.5 ms | WebGL/WebGPU/首次转视角均保持中位数,城市联机减少 0.6 ms |
| WebGPU 预热 | 中位数减少至少 30% | 减少约 84% |
| 真实就绪 | 中位数减少至少 5% | 出生点减少约 13% |
| 正确性 | 错误为零,实际后端/缓冲正确,不下调画质与物理行为 | 30 个样本独立核验通过;构建与相关行为检查保留原门槛 |
统计仍采用 formatVersion: 2。P95、P99、渲染提交 CPU 为每轮统计值的中位数;帧数阈值统计按相同总时长合计。超过 22 ms 用于观察本轮约 25 ms 的尾帧,它不取代 60 FPS 的约 16.7 ms 帧预算。下表的 30 个有效样本经过独立汇总校验,并对应这次矩阵冻结的源码;随后共享加载/取消安全补丁的验收另列在本节末尾,不混合不同版本的样本。
| 场景 | 每版采样 | P95 前→后 | P99 前→后 | 超过 22 ms 前→后 | 超过 50 ms 前→后 | 渲染提交 CPU P50 前→后 |
|---|---|---|---|---|---|---|
| macOS WebGL,已加载街区转视角 | 3×30 秒,独立进程 | 25.1→18.8 ms | 25.8→19.8 ms | 552→0 | 0→0 | 6.6→5.8 ms |
| 浏览器 WebGL,已加载街区转视角 | 3×30 秒,同一进程 | 18.3→18.3 ms | 18.6→18.6 ms | 1→1 | 0→0 | 6.5→5.7 ms |
| 浏览器 WebGPU,已加载街区转视角 | 3×30 秒,同一进程 | 18.4→18.4 ms | 18.7→18.7 ms | 4→2 | 0→0 | 6.9→7.2 ms |
| 浏览器 WebGPU,出生点首次转视角 | 3×15 秒,独立进程 | 18.4→18.5 ms | 18.7→18.7 ms | 0→0 | 0→0 | 7.4→7.0 ms |
| 两个真实城市联机客户端,冲刺并转视角 | 3×10 秒,新房间 | 18.3→17.6 ms | 18.5→17.9 ms | 0→0 | 0→0 | 7.3→7.1 ms |
逐轮 P99 与提交 CPU P50 按各版本自身的第 1/2/3 次样本列出,便于检查波动:
| 场景 | 基线 P99(三轮,ms) | 主矩阵画面版本 P99(三轮,ms) | 基线 CPU P50(三轮,ms) | 主矩阵画面版本 CPU P50(三轮,ms) |
|---|---|---|---|---|
| macOS WebGL | 25.2 / 25.8 / 26.1 | 19.7 / 20.0 / 19.8 | 6.6 / 6.6 / 6.9 | 5.7 / 5.8 / 6.9 |
| 浏览器 WebGL | 18.6 / 18.6 / 18.5 | 18.5 / 18.6 / 18.7 | 6.5 / 6.5 / 6.7 | 5.7 / 5.7 / 5.7 |
| 浏览器 WebGPU | 18.7 / 18.7 / 18.7 | 18.7 / 18.7 / 18.7 | 7.3 / 6.9 / 6.9 | 7.2 / 7.2 / 7.3 |
| 出生点首次转视角 | 18.7 / 18.8 / 18.7 | 18.7 / 18.6 / 18.7 | 7.7 / 7.4 / 6.7 | 7.0 / 6.8 / 7.0 |
| 双客户端城市联机 | 18.7 / 17.8 / 18.5 | 18.0 / 17.6 / 17.9 | 7.3 / 7.3 / 6.9 | 7.3 / 7.0 / 7.1 |
主客户端各组实际 FPS 约 60;联机第二客户端实际使用 WebGPU、720×450 缓冲,采样结束仍为 running。macOS 基线三轮 P95 为 20.3 / 25.1 / 25.2 ms,主矩阵画面版本为 18.9 / 18.8 / 18.5 ms;本组 P99 约减少 23%,超过 22 ms 的帧全部消失,但 P99 仍高于 16.7 ms,不能承诺任意视角和系统负载都不会卡顿。
原生提交 CPU 本组为 6.6→5.8 ms,较早的交替顺序、仅性能补丁对照则为 5.8→5.9 ms;主矩阵画面版本第三轮也达到 6.9 ms。本轮不把原生 CPU 减少描述为稳定的通用收益。持续 WebGPU 本组提交中位数为 6.9→7.2 ms,约增加 4.3%;该字段测世界渲染函数的墙钟,排除最终 HDR 呈现,既不等于完整 GPU 耗时,也不是单独测出的墨线成本。帧间隔稳定不能证明新增计算与显存成本为零。
加载收益与保留的首次转视角表现
| WebGPU 出生点独立样本 | 基线三轮 | 主矩阵画面版本三轮 | 中位数前→后 |
|---|---|---|---|
| 四朝向管线预热 | 2,470.6 / 2,420.6 / 2,460.7 ms | 403.7 / 404.0 / 406.2 ms | 2,460.7→404.0 ms,约减少 84% |
| 真实就绪时间 | 16.492 / 15.733 / 16.006 秒 | 14.111 / 13.919 / 13.797 秒 | 16.006→13.919 秒,约减少 13% |
这组缩短加载的同时,首次转视角 P99 18.7→18.7 ms、超过 50 ms 的帧 0→0,保留了第一轮已经取得的首次转视角效果。独立进程不保证 GPU 驱动缓存完全冷,预热也不覆盖将来所有位置、装备与天气。约 13.9 秒的就绪时间仍包含场景与物理等准备工作,不能把 404 ms 预热说成完整游戏已在同样时间内可操作。
双客户端联机流程耗时中位数 14.949→13.067 秒,约减少 13%;它包含页面加载、建房/加入、准备和开始步骤,仍是流程耗时,不是某一客户端首个可操作帧的精确加载时间。持续样本中的加载数字每个进程只记录一次,不能把同一值重复三次当成三次独立冷启动。
验证与未覆盖范围
矩阵对应版本已通过完整单测 297 文件/1,906 项,最后相关定向 7 文件/47 项;全仓类型检查、Web 与桌面构建、原有发布预算及资源策略检查通过。浏览器真实 GPU 回归 10 项、macOS 正式构建功能回归 1 项通过。WebGL 白天/黄昏/夜景与 WebGPU 白天截图已人工检查;河岸日/夜景也分别检查了 WebGL 与 WebGPU,水面捕获使用既有 512 尺寸与两层级,天空、远景与水面可读,没有 shader 验证错误。截图与原始采样只留在私有本地,不导入公开文档。
正式矩阵之后,最后安全补丁只调整共享加载/取消边界:借用 HDR target 的绘制限制在同步持有范围,相机恢复使用所有权 token,退出立即解除 canvas 隐藏,避免旧准备任务影响重新进入的场景。它不改独立游戏的稳态绘制。补丁后真实 GPU 的正常嵌入挑战与“准备期间立即取消并恢复可见画布”两项回归通过,相关 6 文件/39 项单测及应用类型检查通过;先前 10 项浏览器与 1 项原生功能回归保留各自适用范围。
安全补丁后的全仓类型检查、Web/桌面重新构建、原有发布预算/文件校验、资源策略和 diff 检查通过;重新构建的 macOS 正式版本 F8、偏好持久化与本地城市功能回归再次通过。最后安全版本的独立补测另列下节,原有 30 样本矩阵按主矩阵画面版本保留。
宽视角绘制仍约 390 次/12.9 万三角形,历史局部场景目标仍需按各自范围处理;没有提高目标或宣称整图预算合格。步行弹性只覆盖本地自由探索的骑手显示层。实际 Steam/云端公网、Safari/Firefox、Windows、实体手机、其他 GPU、macOS 生产 WebGPU、新区域与长时间内存稳定性未在这组矩阵完成验收。原生窗口 harness、正式包装功能检查、标准节流启动 suite 与完整 release:check 有各自边界;上一轮记录的原生指针捕获 WrongDocumentError 也没有被这组 harness 转视角替代验收,本轮不将这些边界合并为一项全部通过的结论。
最后安全版本的独立补测
最后安全版本按共享加载/取消补丁重新冻结,与上面的主矩阵画面版本分开记录。三组独立首次转视角 A/B 和一组新联机房间 A/B 已完成;补测不与原有 30 个样本合并计算一个“最终中位数”。应用中只有共享城市渲染与预热 helper 及其测试四个文件变化,持续游玩的渲染、原生 WebGL 限帧与画面参数保持主矩阵版本。
首次转视角仍使用三个独立进程,按前/后、后/前、前/后串行采样,每次 15 秒;后端、场景、输入、缓冲尺寸和正式采样开关沿用主矩阵。各轮结果如下:
| 指标 | 基线三轮 | 最后安全版本三轮 | 各轮中位数前→后 |
|---|---|---|---|
| 四朝向预热 | 2,944.4 / 2,803.9 / 2,779.1 ms | 456.3 / 467.0 / 476.1 ms | 2,803.9→467.0 ms,约减少 83% |
| 真实就绪 | 17.781 / 17.276 / 17.284 秒 | 14.295 / 15.094 / 15.341 秒 | 17.284→15.094 秒,约减少 13% |
| 帧间隔 P95 | 17.4 / 17.5 / 17.5 ms | 17.0 / 17.6 / 17.5 ms | 17.5→17.5 ms |
| 帧间隔 P99 | 17.8 / 17.8 / 17.8 ms | 17.3 / 17.9 / 17.7 ms | 17.8→17.7 ms |
| 世界提交 CPU P50 | 7.9 / 8.0 / 8.7 ms | 7.4 / 7.5 / 8.1 ms | 8.0→7.5 ms |
这组三轮每版合计 45 秒,超过 22 ms 的帧 3→0,超过 50 ms 的帧 0→0,各轮实际 FPS 59.927–60.051。预热约减少 83%,就绪约节省 2.19 秒,首次转视角没有长帧回归;它与主矩阵的改善方向一致,仍属于各自系统窗口,不能混用主矩阵的基线与本组优化值计算收益。
最终新联机房间补测为每版两个真实客户端、主客户端采样 10 秒的一组对照:P95 17.6→17.3 ms,P99 17.7→17.5 ms,世界提交 CPU P50 8.1→7.9 ms,实际 FPS 59.907→59.939,超过 22/50 ms 的帧均为零。第二客户端为实际 WebGPU、720×450 缓冲,结束时仍为 running。流程耗时 16.672→14.351 秒保留原有计量边界;单组用于核对安全补丁,没有替代主矩阵的三组联机验收。
八个补测样本的实际后端与缓冲正确、相机确实旋转、游玩状态有效、运行时及 GPU 验证错误为零,预先约定的加载与帧耗时门槛通过。共享加载增加的四次 fullscreen resolve 只发生在隐藏的准备阶段,持续游玩无新增 pass;相关恢复、释放、画面与打包检查已通过。本轮指定本机、路径与模式的 Goal 验收完成,后续区域、设备、公网与长期运行仍保留上节边界。
Windows 长距离骑行与追击(2026-10-14)
本轮针对当前 Windows 11 x64、RTX 4080、Electron 44.7.0/Chromium 152,验收实际跨街区骑行的最低完整一秒帧数不低于 60。原生窗口 harness 使用 WebGL、1440×900 缓冲、DPR 1、90 FPS 上限、白天晴天、第三人称、HDR 半浮点目标与 4× MSAA,保留既有阴影、水面和物理频率。默认 60 FPS 上限未改变;本机在该上限下会出现完整一秒 59 帧,因此验收使用已有的 90 FPS 设置留出余量,不能将 59 四舍五入为达标。此范围不覆盖更大的全屏缓冲、其他 GPU 或全部天气。
冻结完整应用源码后,先定位到灯光数量随远处建筑隐藏发生变化,跨区域首次使用新配置触发约 2.1–2.3 秒着色器编译。修复将两盏庭院灯保持注册,远处强度归零,避免全场景灯光配置反复变化。单独扩充预热未消除该停顿,失败记录保留;原生 WebGL 预热仍覆盖主场景与水面捕获的实际层级、雾状态,并在成功或失败后恢复场景。代价是远处仍保留两盏零强度灯及加载阶段的编译工作,不能宣称额外计算为零。
追击原有路网规划间隔为 0.65 秒,直接追击仍使用上次规划的玩家位置,接近该位置后会短暂停住;警察显示又随普通路人按 30 Hz 重建。现在可通行的近距离末段逐模拟步跟随玩家,仅警察的 14 个实例部件逐渲染步更新,保留路网规划、碰撞检查与拦停流程。远距离路人和车辆的更新频率不变,绘制调用未增加;额外代价为近距离通行查询和少量矩阵/颜色上传。
正式方法为独立进程、关闭 profiler/trace,按优化版/基线、基线/优化版、优化版/基线串行交替。路线从艺苑路出发,经过广州塔、TIT 北侧、客村及丽苑;通过普通油门、刹车、转向和倒车输入移动,遇停车障碍按真实碰撞查询绕行,保留警察追击和检查。只在计时前设置起点,采样期间不传送、不忽略碰撞。路线完成后结束计时,最长六分钟;一秒 FPS 按实际采样中的完整一秒窗口统计,包含停顿,末尾不足一秒不参与最低值。
腾讯方向自动路线在艺洲路段受碰撞边界阻挡,未完成的样本不纳入正式对照;广州塔折返轨迹的自动驾驶回退问题也单独修正。五分钟探测已实际骑行约 4.17 公里,最低一秒 76 帧,但未到达末站,因此仍保留为未完成探测,不替代完整路线验收。原始日志、轨迹、源码与 profiler 均留在私有本地,公开文档只记录方法、汇总和限制。
完整路线三组结果
六个正式样本均完成约 4.419 公里的实际骑行,经过艺苑路、艺洲路、赤岗北路、广州塔路、新港中路及丽岗街,实际后端为 WebGL,缓冲始终为 1440×900,画质参数一致,结束仍在游玩,运行时错误为零。顺序为 C1/B1、B2/C2、C3/B3;以下各列按同版轮次排列。
| 指标 | 基线 B1 / B2 / B3 | 优化 C1 / C2 / C3 |
|---|---|---|
| 完整一秒最低 FPS | 0 / 0 / 0 | 74 / 76 / 73 |
| 实际平均 FPS | 81.16 / 81.16 / 82.44 | 82.29 / 82.68 / 82.67 |
| 帧间隔 P95(ms) | 21.7 / 21.3 / 20.9 | 21.5 / 21.1 / 21.1 |
| 帧间隔 P99(ms) | 23.5 / 23.0 / 22.1 | 23.3 / 22.8 / 22.6 |
| 最大帧间隔(ms) | 2171.1 / 2155.2 / 2237.8 | 81.3 / 60.5 / 74.6 |
| 超过 50 ms 的帧数 | 14 / 15 / 20 | 18 / 6 / 8 |
| 超过 50 ms 的次数/分钟 | 2.60 / 2.78 / 3.71 | 3.36 / 1.12 / 1.49 |
| 超过 16.7 ms 的帧比例 | 23.15% / 23.67% / 22.63% | 22.87% / 23.20% / 23.11% |
| 世界提交 CPU P50(ms) | 6.5 / 5.9 / 5.7 | 6.6 / 5.9 / 5.8 |
| 世界提交 CPU P95 / P99(ms) | 8.5/9.3 · 7.7/8.3 · 7.5/8.2 | 8.5/9.2 · 7.6/8.1 · 7.5/8.0 |
| 回调至呈现 CPU P50(ms) | 7.6 / 6.9 / 6.8 | 7.8 / 7.0 / 6.9 |
| 回调至呈现 CPU P95 / P99(ms) | 9.8/10.7 · 8.9/9.7 · 8.8/9.6 | 9.8/10.6 · 8.9/9.5 · 8.8/9.5 |
| 真实就绪(秒) | 13.557 / 13.621 / 14.413 | 14.357 / 16.193 / 14.200 |
| 管线预热(ms) | 0.6 / 0.6 / 0.6 | 1015.8 / 2557.9 / 1044.9 |
| 路线采样时长(秒) | 323.390 / 323.349 / 323.418 | 321.188 / 321.182 / 321.203 |
| 末尾 JS 堆单点(MiB) | 1131.9 / 1085.4 / 1130.6 | 1905.5 / 1318.5 / 1937.1 |
各轮中位数:P95 为 21.3→21.1 ms,P99 为 23.0→22.8 ms;P99 范围为 22.1–23.5→22.6–23.3 ms,常态间隔改善很小。最大帧间隔中位数 2171.1→74.6 ms,最低一秒帧数中位数 0→74,优化三轮范围 73–76,满足本机约定的 60 门槛。超过 50 ms 合计 49→32,但采样时长不同,归一后的总体发生率为 3.03→1.99 次/分钟;第一轮优化的次数反而更多,因此不能说每轮长帧均减少。P95/P99 仍超过 16.7 ms,不能把完整一秒最低值达标说成每一帧均在 16.7 ms 内。
世界提交 CPU P50 中位数保持 5.9 ms,回调至呈现中位数 6.9→7.0 ms,P95 中位数保持 8.9 ms。GPU 未单独计时,不能据此宣称零 GPU 成本。就绪中位数 13.621→14.357 秒,约增加 0.736 秒,优化版范围 14.200–16.193 秒;这包含约 1.0–2.6 秒的原生 WebGL 预热,是消除游玩期编译停顿的加载代价。
JS 堆末尾读数偏高,不能隐去,也不能由单点推断持续保留或泄漏。另用独立进程、同一启动场景与一秒转视角作一次强制回收诊断,基线与优化回收后分别约 1035.7 / 1036.3 MiB;该单对诊断不与正式 FPS 结果合并,也不覆盖骑行末尾的保留或数小时运行。正式样本仍按原始值报告,长期内存稳定性尚未验收。
最终全仓类型检查与单测 336 文件/2264 项通过,Windows 生产构建预算保持原有上限。原生打包兼容回归覆盖 100%/125%/150%/200% 缩放、中文及空格存储路径、键盘焦点、最小化、全屏、图形上下文恢复、偏好持久化、城市场景、WebGPU 实际设备启动和广州塔水池反射。WebGPU 功能通过不代表本轮 WebGL 长途帧率结论适用于 WebGPU;原生 harness 与正式包装功能检查保留各自边界。真实 Steam 联机、公网服务、实体手柄、其他 GPU、大缓冲全屏、全部天气与长期内存未在本轮完成验收。
2026-10-14:广州 Godot 动态街道与僵尸压力原型
本轮在 Apple M1 Pro/32 GiB/macOS 26.6.2 上继续验证 Godot 4.7.2 Forward+ Metal 原型。动态街道导入同一来源的 192 名行人、96 辆停放车辆、双向新港公交线路与 6 个 OSM 站点;公交保留班次、跟车、信号灯、停车及开门。7,200 个 60 Hz tick 的数值对照通过,公交及行人最大误差约 4.5e-13;原有 14 组骑行、574 个状态和 3,957 个支撑/地面探针也通过。一个既有岸边浮点分类保留 0.2 毫米空间容差。
压力玩法新增原生障碍扫掠、邻居分离、受击、射击/换弹、近战、攻击冷却与尸体动画。两类实例化网格在 shader 中计算四肢动画,所有存活敌人仍每秒更新 60 次。道路追逐复用共享反向 BFS,图计算使用 worker,物理查询留在主物理线程;保留两秒的规划周期和后续短路段。实体墙绕行、抵达攻击范围、墙体阻挡射击/近战及伤害/弹匣回归通过。它是 300/500 活体压力原型,尚未移植生产版完整任务、武器、车辆交互、跨平台及联机权威,不能视为现有 32 敌人联机玩法的等价移植。
严格的原生 A/B 统一增强档光照、4 级联 4096 阴影、SSAO、SSIL、SSR、HDR 墨线、水面 512²/20 Hz 捕获、1821×1138 缓冲、4× MSAA 与 60 Hz 物理。头部余量窗口关闭 VSync、统一限制 90 FPS,默认显示同步另行观察;这不改变默认游戏设置。静态候选采用 128 米合批、位置融合阴影网格、验证过的闭合不透明体遮挡及解析地面索引;其他导入 LOD 和距离阈值保留。基线具备相同动态街道与道路追逐,保留未合批图和原始地面采样。编辑器、MCP helper、profiler 和 trace 关闭,每轮独立进程,顺序为前/后、后/前、前/后。
| 300 活体同屏、实际骑行 | 基线 | 最终候选 |
|---|---|---|
| 样本 | 三轮各 40 秒 | 三轮各 40 秒 |
| FPS 中位数 | 60.33 | 62.16 |
| 最低完整一秒帧数 | 54 | 55 |
| P95 / P99(ms) | 21.39 / 25.58 | 21.03 / 24.32 |
| 最大帧间隔(ms) | 62.17 | 44.57 |
| 超过 50 ms(三轮合计) | 1 | 0 |
| 进程 CPU 中位数 | 109.1% | 99.2% |
| 物理/玩法 CPU P50(ms) | 5.89 | 4.21 |
| 可见绘制读数 P50 | 2,391 | 1,749 |
| 可见图元读数 P50 | 1,279,674 | 1,290,465 |
| 缓存已存在的新进程就绪(s) | 4.88 | 9.17 |
候选平均为 62.09–62.20 FPS,最低一秒分别为 60 / 55 / 56。严格的全程完整一秒至少 60 帧标准尚未达标;平均大于 60、局部 CPU 降低或本组没有超过 50 ms 的帧都不代表全程不卡顿。每轮 300 个活体持续活动,采样时身体中心均在视锥内,这不证明全部身体完全无遮挡。六个最终窗口共有 79 个每 30 tick 采样的骑行状态,位置、高度、速度、方向和碰撞差异为零。
合批与遮挡同时有代价:首次 128 米缓存构建约 36.45 秒,首次实际就绪约 45.06 秒;已有缓存时上述就绪仍较基线慢约 4.3 秒。该缓存及导出的模型是本地开发数据,未交付发布安装包,资源分发与体积预算未放宽。CPU 的 100% 表示一个核心,原生进程和现有桌面进程树不能直接换算为同款完整游戏节省比例。RSS 受共享内存、压缩及换页影响;Metal GPU 时间戳不可用,不用 0 值判断 GPU 成本。后台应用没有完全隔离,只覆盖本台设备。
保留的未采用候选包括:320 米合批减少更多绘制命令,但可见图元增加约 10%,重复 300 活体窗口仍低于 60 FPS;160/96 米没有提供更稳的最低一秒;物理体空间分区通过 1,437 次扫掠及 479 次占用对照,但没有稳定的速度收益;Jolt 候选明显改变本条骑行路线的碰撞/轨迹;独立渲染线程出现文字纹理初始化引擎错误。这些诊断及被替代、未达标和中止样本均保留,未混入最终正式统计。
长途场景计划路线 4.61 公里,每轮真实骑行 4.243 公里、16,527 个物理 tick,约 275.45 秒;300 活体一直更新,途中会离开视野。三个前后窗口共有 550 个同 tick 骑行状态,位置、高度、方向、速度及碰撞差异为零。统计口径与上表相同;本组不能代替 300 只同屏验收。
| 300 活体长途骑行,三轮前/后 | 基线 | 最终候选 |
|---|---|---|
| FPS 中位数 | 62.48 | 69.07 |
| 最低完整一秒帧数 | 27 | 37 |
| P95 / P99(ms) | 24.06 / 29.79 | 21.70 / 27.41 |
| 最大帧间隔(ms) | 63.83 | 69.46 |
| 超过 50 ms(三轮合计) | 5 | 4 |
| 进程 CPU 中位数 | 112.2% | 103.0% |
| 物理/玩法 CPU P50(ms) | 5.32 | 3.62 |
| 可见绘制读数 P50 | 2,157 | 1,572 |
| 已有缓存的新进程就绪(s) | 4.86 | 8.03 |
| 本组最大 RSS(GiB) | 1.39 | 1.28 |
全路线平均 FPS 提高约 10.5%,物理/玩法 CPU P50 减少约 31.9%,进程 CPU 读数减少约 8.2%,P99 减少约 8.0%;但最大长帧反而更高。三轮候选最低一秒分别为 46 / 37 / 40,复杂街区稳定 60 FPS 与骑行不卡顿目标仍未通过。已有缓存的启动中位数慢约 3.2 秒,128 米本地缓存另占约 78.75 MiB;首次准备代价见上文。
500 只压力窗口只有候选,三个独立进程各 40 秒,FPS 为 61.85 / 58.39 / 52.30,中位数 58.39;最差完整一秒 41 帧,P95 / P99 中位数 21.55 / 28.51 ms,最大长帧 82.47 ms,三轮合计 2 帧超过 50 ms。每轮 500 活体持续更新,定期采样至少 483 个中心在视锥内。CPU 中位数 114.5%,物理/玩法 P50 6.98 ms,就绪中位数 8.41 秒,最大 RSS 2.20 GiB。此组也未达到稳定 60 FPS。
另外从完整冻结的现有工作区复用既有相机 benchmark,与最终原生基础/增强档各采三个独立进程、串行交替。短程真实加速/刹车/倒车、无僵尸、40 秒,统一 1821×1138 缓冲、4× MSAA、60 Hz 骑行和 60 FPS 上限,保留正常显示同步。它是动态街道参考,不与上面的 90 FPS 余量或 300 活体窗口计算收益。
| 无僵尸短程参考,三轮 | 现有 Electron / WebGL | Godot 基础档 | Godot 增强档 |
|---|---|---|---|
| FPS 中位数 | 59.95 | 59.73 | 57.98 |
| 最低完整一秒帧数 | 52 | 56 | 51 |
| P95 / P99(ms) | 23.10 / 25.90 | 20.55 / 21.90 | 24.44 / 25.46 |
| 最大帧间隔(ms) | 107.30 | 56.35 | 119.59 |
| 超过 50 ms(三轮合计) | 3 | 4 | 1 |
| 已有缓存的新进程就绪(s) | 10.49 | 8.32 | 7.91 |
| 进程树 CPU 中位数 | 112.8% | 79.6% | 90.3% |
| 本组最大 RSS(GiB) | 3.94 | 1.86 | 2.20 |
九个参考窗口共有 79 个同 tick 状态,位置误差不超过 5e-13 米、速度误差不超过 7.2e-15 m/s,方向误差约 4.4e-8 弧度,碰撞状态一致。尚未完成严格同画质跨引擎验收:原生增强档有额外 SSAO/SSIL/SSR 与多级阴影,水面裁剪、植被和速度相关 FOV 仍不同;完整战斗与公交交互也没有完全对齐。基础档尾帧在本组较低,增强档仍低于 60 FPS,不能归纳为 Godot 同画质必然更快。现有侧 CPU/RSS 含开发 harness 的 Node/Vite/Electron 进程树,就绪起点与原生侧也不完全相同;不是生产安装包或整机成本对照。
2026-10-14–15:Three.js 与 Godot 的 300 活体骑行压力对照
本轮复用 Apple M1 Pro/32 GiB/macOS 26.6.2,Three.js 0.186.1/Electron 44.7.0/Chrome 152 WebGL Metal,对照上述冻结的 Godot 4.7.2 Forward+ Metal 增强原型。Three.js 新增开发压力适配器,把同一广州地图中的 300 活体追逐扩展成可重复负载;参考组使用全邻居扫描、逐敌人 BFS 和原有 CPU 四肢动画,候选使用空间邻居查询、共享反向 BFS worker 和合并网格 GPU 动画。每只活体仍每秒更新 60 次,离开视野后也持续活动,保留障碍扫掠、绕行、攻击范围及冷却。
Three.js 内部 A/B 保留原有身体几何、三角形数量、颜色、光照、水面、阴影、HDR、骑行模型与真实 Rapier 碰撞。顶点对照覆盖两类角色、多个动画时刻与尸体姿态;真实 Metal WebGL 角色夹具三角形数量不变,绘制从 7 次降到 3 次,但少量边缘像素有浮点/抗锯齿差异,并非逐像素相同。另对共享身体分离建立保留原配对顺序的空间索引:300 个分散实体的高度读取由 179,400 次降至不足 3,000 次,密集、墙边、重叠及不同楼层样本的最终位置保持一致。这是局部工作量证据,不能推断整体帧率收益。
正式矩阵完整冻结应用、共享包、依赖、资源与共同 harness,每版本每场景三个独立进程,顺序 B/C/G、C/G/B、G/B/C。依用户选择暂停另一项画风 GPU 采样,关闭 Godot 编辑器、AI/MCP helper、profiler 和 trace,正式窗口串行运行。前期有并发 GPU 工作的诊断样本保留但排除;不混用前一节较早的 Godot 成绩。实际缓冲均为 1821×1138、4× MSAA、60 Hz 物理,90 FPS 余量上限、关闭 GPU VSync,白天晴朗;浏览器仍受 compositor 回调调度影响,不把这些 FPS 当作纯 GPU 吞吐。
短程为真实加速、刹车、倒车,俯视相机,每轮 40 秒。FPS、P95/P99、CPU、就绪取各轮中位数,最低完整一秒和最大帧间隔取本组最差值,长帧同时报告合计及按总时长归一的每分钟次数。
| 300 活体同屏短程 | Three.js 参考 B | Three.js 候选 C | Godot 增强 G |
|---|---|---|---|
| FPS 中位数 | 75.65 | 64.59 | 51.46 |
| 各轮 FPS 范围 | 60.04–75.65 | 59.94–72.35 | 50.41–51.52 |
| 各轮最低完整一秒 | 44 / 62 / 66 | 57 / 48 / 57 | 48 / 48 / 37 |
| P95 / P99(ms) | 26.30 / 29.10 | 28.80 / 32.10 | 26.36 / 29.19 |
| 各轮 P99 范围(ms) | 29.00–34.30 | 30.60–35.10 | 29.01–30.09 |
| 最大帧间隔(ms) | 121.30 | 153.10 | 63.79 |
| 超过 50 ms,三轮合计 | 4 | 7 | 2 |
| 超过 50 ms,次数/分钟 | 2.00 | 3.50 | 1.00 |
| 进程 CPU 中位数 | 149.2% | 149.5% | 93.0% |
| 敌群逻辑 CPU P50(ms/tick) | 1.30 | 1.40 | 3.49 |
| 已有资源/缓存,新进程就绪(s) | 15.00 | 14.04 | 11.86 |
| 游玩窗口最大进程树 RSS(GiB) | 3.60 | 3.54 | 2.04 |
三组均未达到稳定 60 FPS。 Three.js 候选同屏 FPS 中位数较参考低约 14.6%,长帧更多,敌群 CPU P50 也没有改善;各轮范围存在明显波动,不据此归纳为所有情况下都更慢。局部绘制数降低没有带来本场景稳定收益,因此 GPU 动画保留为压力实验的显式选项,正式玩法默认路径没有切换。正式联机敌人数上限仍为 32,此压力适配器尚未迁移完整任务、武器与联机权威。压力采样固定玩家生命、不射击,继续计算追逐、碰撞与攻击,以保持 300 活体;不证明完整战斗下的存活能力。
九个短程窗口共有的 79 个同 tick 骑行状态中,Three.js 内部位置、高度、速度、方向和碰撞差异为零;跨引擎位置误差小于 5e-13 米、速度误差约 7.2e-15 m/s、方向误差约 4.4e-8 弧度,碰撞状态一致。每个窗口定期采样的 300 个身体中心均位于视锥内,这不证明身体完全无遮挡。
CPU 为每 0.5 秒读取的进程树读数,100% 表示一个核心;汇总按就绪后四秒至游玩窗口结束筛选原始样本,排除加载及退出。Three.js 包含 Node/Vite/Electron、renderer 和 helper,Godot 为原生进程,范围不同;RSS 汇总包含共享页重复计数,不能据此判断长期泄漏或生产安装包的内存节省。macOS helper 名称不能可靠拆分 GPU 子进程 CPU,Metal GPU 时间不可用,不将 0 值解释为无 GPU 成本。后台非 GPU 应用未完全隔离,未覆盖其他 GPU、全屏大缓冲、其他天气或数小时运行。
本轮尚未完成严格同画质、完整同玩法的跨引擎验收。 Godot 保留额外 SSAO/SSIL/SSR、多级阴影、原型碰撞与显示路径;公交/警察、视角、水面裁剪和植被尚未完全对齐。它对照的是当前两个原型的实际成本,不能由该表宣布同画质下某引擎必然更快,也没有通过降画质来获得 60 FPS。
长途采用相同的 179 点、计划 4.61 公里路线,初始放置后实际使用骑行控制与碰撞。Three.js 每轮约 324.4–324.7 秒、实际 4.428–4.429 公里;Godot 每轮约 275.45 秒、实际 4.243 公里。Three.js 内部保留原有完整街道与警察行为,Godot 的世界碰撞与该行为尚未完全移植,因此跨引擎不是同一条实际轨迹;短程 motor 数值对齐不能代替全路线行为验收。300 活体全程更新,途中会离开视野,这组不能代替同屏验收。
| 300 活体长途,三轮 | Three.js 参考 B | Three.js 候选 C | Godot 增强 G |
|---|---|---|---|
| FPS 中位数 | 55.53 | 67.35 | 55.03 |
| 各轮 FPS 范围 | 54.02–73.70 | 61.70–75.70 | 47.98–60.23 |
| 各轮最低完整一秒 | 22 / 42 / 48 | 46 / 42 / 56 | 35 / 31 / 34 |
| P95 / P99(ms) | 32.40 / 37.10 | 28.50 / 32.90 | 32.23 / 35.48 |
| 各轮 P99 范围(ms) | 31.10–39.10 | 29.10–35.10 | 29.89–37.36 |
| 最大帧间隔(ms) | 323.50 | 154.10 | 130.76 |
| 超过 50 ms,三轮合计 | 47 | 48 | 15 |
| 超过 50 ms,次数/分钟 | 2.90 | 2.96 | 1.09 |
| 进程 CPU 中位数 | 154.0% | 155.1% | 99.6% |
| 敌群逻辑 CPU P50(ms/tick) | 1.70 | 1.50 | 2.98 |
| 已有资源/缓存,就绪字段(s) | 14.26 | 13.21 | 10.85 |
| 游玩窗口最大进程树 RSS(GiB) | 3.59 | 3.51 | 1.21 |
Three.js 长途候选的 FPS 中位数提高约 21.3%,P99 减少约 11.3%,敌群逻辑 CPU P50 减少约 11.8%;三轮各自 FPS 提高约 24.7% / 11.1% / 2.7%,收益幅度并不稳定。最大帧间隔降低,但超过 50 ms 的发生率没有下降,进程树 CPU 也没有下降。候选最低一秒仍只有 42 帧,P95/P99 都大于 16.7 ms。长途三组仍未达到稳定 60 FPS,不能保证骑行不卡顿或完整 300 敌人玩法流畅。
就绪字段起点不同:Three.js 为 Node harness 启动至进入场景,Godot 为场景脚本自报告,含已有本地缓存但不包含首次资源恢复;不能直接计算跨引擎启动加速比例。CPU 样本按这些字段近似定位游玩窗口,采样分辨率为 0.5 秒,启动起点差异也是方法限制。Godot 原有首次 128 米缓存准备约 36.45 秒、首次就绪约 45.06 秒及约 78.75 MiB 缓存代价仍保留,未用本轮已有缓存的数据替换。
三份冻结源码/清单的 1,125 / 1,125 / 290 个文件在矩阵结束后哈希未变化;正式窗口没有渲染错误。现有挑战进入、移动、开火/近战、退出恢复与桌面俯视骑行切换的两个真实 Metal WebGL 功能回归通过。原始日志、图像及进程样本保留在私有实验目录,未发布到公开文档或作为媒体进入 Git。完整生产 300 活体权威、严格跨引擎画质/全路线行为及稳定 60 FPS 尚未验收。
最终相关单测 48 文件/445 项、全仓类型检查、构建、126 个文档参考输入检查与 Git 资源检查通过;网页发布检查通过,556 个文件,开发压力代码未打包。原有体积上限保持不变,完整资源 19.63 MiB/20.00 MiB、Rapier 1.16 MiB/1.25 MiB。另一个画风任务在本轮 GPU 与 CPU 校验全部结束后收到恢复正式采样的通知,后续样本不计入此矩阵。
2026-10-15:增强配置、完整立面与共享碰撞对照
本轮保留原生增强效果,为 WebGL 对照加入四级阴影、SSAO、SSIL、48 步 SSR 与 HDR 光晕。实际主缓冲均为 1821×1138、4×MSAA,客户区均为 1440×900;四级阴影共 4096² 像素、220 米范围,AO/间接光使用半尺寸,平面反射为 820×512。保持原有地图、骑行调校、动态街道与公交,并使用同源 Rapier 0.36.0 的原生/WASM 查询内核覆盖骑行、相机、僵尸与公交碰撞。
截图复核后补齐了动态索引遗漏的原生立面、完整道路标线与水面反射,并修复 WebGL 用骑行者方向筛选立面、导致高位相机与反射漏掉窗户的问题。最终增强对照保留完整近处立面,距离边界、105/125 米细节阈值和组级迟滞状态取自相同来源。四个真实 WebGL 视角与完整立面参考逐像素一致;静态提交优化另有六个主相机/阴影视图的逐像素回归。玻璃、远景窗纹、雾和水面反射/折射的实际着色仍有差异,因此下列结果属于相同增强效果配置的原型比较,不能解释为所有像素一致、最终商业画质或普遍的引擎排名。
横向碰撞的 720 组、每组 11 项真实原生/WASM 查询最大数值差约 1.8e-15,覆盖支撑面过滤、水位下相机、移动/占位、射线和公交盒体。骑行、支撑高度、路线控制、7,200 tick 公交状态和战斗行为另做回归。完整长途仍会因动态交通与数值分支产生实际轨迹和耗时差异,不能把相同控制策略说成逐帧完全相同的行驶过程。
正式范围为自由骑行、僵尸与公交,双方均不包含剧情拘捕。压力窗口固定玩家生命,保持 300 活体追逐、碰撞与攻击,计时中不持续开枪以免数量降低;射击、近战、遮挡、受击和装填单独验证。生产联机上限仍为 32,本轮不承诺完整 300 人联机或所有战斗负载。
Apple M1 Pro、32 GiB,Godot 4.7.2 Forward+ Metal,对照为 Electron 44.7.0 / Chrome 152 WebGL ANGLE Metal。完整独立工作区、依赖、媒体和准备资源共冻结 65,098 个文件、约 2.85 GB,每个窗口开始前校验 SHA-256。前期缺失立面、错误水面、提交几何错误、异常退出和 profiler 样本保留并排除,最终完整立面矩阵重新采集。计时结束后无新绘制可能使截图等待挂起,现已在计时结束后强制绘制一次最终帧,正式版使用该修复。
300 只同屏为三轮各 40 秒,关闭 VSync、90 FPS 上限以观察吞吐余量;顺序为参考/优化/原生、原生/优化/参考、参考/优化/原生。长途为相同 7.04 公里规划路线、各两个新进程、60 FPS 上限且关闭 VSync,优化/原生、原生/优化串行运行。长途中持续更新 300 活体,但不要求全部在视野内。正式窗口没有编辑器、MCP helper、profiler、trace、构建或其他正式 GPU 采样。
FPS、P95/P99 与进程树 CPU 跨独立样本取中位数,最低完整一秒、最长帧及 RSS 保留全部样本最差值,超过 50ms 的次数合计。CPU 取操作系统累计 CPU 时间差,100% 表示一个逻辑核心,仅统计游戏应用进程树,不含 Node/Vite 控制器;进程 RSS 求和可能重复共享页面,不能等同物理内存节省。资源与几何缓存预先准备、磁盘缓存未清空,新进程就绪不是全新安装的冷启动。严格稳定 60 预设为每个完整一秒至少 60 帧、P99 不超过 16.667ms、无超过 50ms 的帧;平均值超过 60 不代表通过,关闭同步下的回调间隔也不替代默认显示同步的呈现验证。
300 只同屏,40 秒 × 3,90 FPS 上限
| 指标 | Three.js 增强基线 | Three.js 优化 | Godot 优化 |
|---|---|---|---|
| FPS 中位数 | 43.49 | 72.39 | 71.81 |
| 逐轮 FPS 范围 | 43.28–43.67 | 67.92–73.81 | 71.78–72.02 |
| 最低完整一秒帧数 | 31 | 52 | 69 |
| P95 / P99(ms) | 36.30 / 41.40 | 26.20 / 28.40 | 21.29 / 21.96 |
| 最长帧(ms) | 350.30 | 53.00 | 35.56 |
| 超过 50ms,全部轮次合计 | 8 | 1 | 0 |
| 游戏进程树 CPU | 229.2% | 131.5% | 107.1% |
| 已有缓存的新进程就绪(s) | 9.12 | 8.64 | 9.69 |
| 最大进程树 RSS(GiB) | 3.37 | 3.34 | 1.58 |
| 实际物理更新频率(Hz) | 59.34 | 60.01 | 60.01 |
300 活体完整长途,各两趟,60 FPS 上限
| 指标 | Three.js 优化 | Godot 优化 |
|---|---|---|
| FPS 中位数 | 54.14 | 59.24 |
| 逐轮 FPS 范围 | 50.08–58.20 | 59.19–59.29 |
| 最低完整一秒帧数 | 35 | 39 |
| P95 / P99(ms) | 29.25 / 34.35 | 19.31 / 25.01 |
| 最长帧(ms) | 188.80 | 78.68 |
| 超过 50ms,全部轮次合计 | 11 | 7 |
| 游戏进程树 CPU | 138.8% | 96.0% |
| 已有缓存的新进程就绪(s) | 9.42 | 10.83 |
| 最大进程树 RSS(GiB) | 3.31 | 1.66 |
| 实际物理更新频率(Hz) | 59.99 | 60.00 |
Three.js 相对本轮新加增强效果后的基线,同屏 FPS 中位数提高约 66.5%,应用进程树 CPU 减少约 42.6%。此收益不代表对原来较轻画质版本的提升。优化后的同屏 FPS 中位数接近,Godot 的 P99、最慢完整一秒与长帧记录更稳,应用 CPU 也较低。
长途 Godot 两轮为 59.19–59.29 FPS、最低一秒 39/41 帧;Three.js 为 50.08–58.20 FPS、最低一秒 35/50 帧,轮次波动明显。保留全部结果,未排除较差的第二趟。两边 P95/P99 仍超过 16.667ms,并有长帧,均未通过严格稳定 60 FPS,不能保证骑行全程不卡顿。
四个长途均完成规划路线,Three.js 每趟约 394.2–394.4 秒、实际约 6.93 公里,Godot 约 384.1 秒、实际约 6.92 公里。相同规划路线、控制策略和碰撞查询不等于完全相同的实际行驶轨迹。本轮所有 13 个窗口通过场景检查,采样后全部 65,098 个冻结文件哈希未变化。已有几何缓存不代表首次准备:本轮原生副本首次合批与就绪约 36 秒,后续新进程就绪仍约 9–13 秒;准备与缓存代价没有从成本中消失。
原始数据、逐轮日志、完整独立工作区和 14 张真实缓冲截图仅保留于本地私有实验目录。PNG 为 1821×1138 原图,未做调色或 AI 重绘;六组同位置街景与一组同屏压力截图同时保留实际着色差异。
最终桌面构建与类型检查、相关 20 项回归、真实 WebGL/WebGPU 功能检查、126 个文档参考输入检查与 Git 资源检查通过;城市合作入口为 511.3/512 KiB,原预算未放宽,发布产物检查通过。Godot AI 最新独立编辑器副本也完成增强档骑行与射击联调,观察到约 18 米行驶、7 次击杀并确认输入释放;首次编辑器启动未传增强参数导致的初始化失败已保留并修复。锁血联调只验证功能,未混入正式性能数据,也未用于宣称完整战斗平衡或稳定 60 FPS。
2026-10-15:原生可玩切片与邻居计算
Three.js 仍是正式主版本。Godot AI 社区 MCP 接通的原生实验增加了骑行、三个原有取送任务、独立本地存档与双人局域网共乘;保持增强效果、1821×1138、4×MSAA、4096 四级阴影、60 Hz 逻辑及原有碰撞后端。新功能属于原生验证切片,未移植完整剧情、四人自由移动、Steam/云房间、账号云存档或跨平台安装包,不能当成生产版等价迁移。
任务复用原地点、停车条件和计分。零敌人、headless 固定步加速的隔离测试实际扫掠骑行约 3.39 公里,完成三单、910 分并保存;这只验证任务、骑行和存档链。真实伤害的 300 只实机测试完成第一单、受伤、击杀与补给,之后自动骑手被围死;跨进程恢复检查点及调整回程、瞄准后仍有失败。300 只连续实战完成三单尚未通过,没有使用锁血、提高生命或减少敌人来宣称通过。
存档格式 2 兼容格式 1,校验完整状态并原子替换,支持备份及未来版本保护;保存敌人击退、弹药、骑行姿态、任务、公交和行人时钟,暂停读档与时钟回退回归通过。原生存档独立于 Three.js。协议 3 的双人共乘由主机驾驶、后座射击,主机计算全部伤害与任务,客户端只提交操作;使用 15 Hz 快照、30 Hz 操作、插值及超时释放。最终 25 秒双进程实机验证接收 375 个快照、零校验拒绝,双方 9 击杀、100 生命与弹药一致;恢复检查点后同房间保持连接,世界版本与街道时钟继续同步。约 12 ms 的回环 RTT 不能外推跨机器或公网,也不是长时联机验收。
不改变逻辑的原生邻居计算
把邻居分离中的跨语言逐对查询改为一次原生批量计算,保持相同网格、遍历顺序、60 Hz 更新、全部碰撞及伤害。20 组、6,000 个代理的向量最大差异为零,邻居计数相同。任务/存档/输入/300 敌人快照的 44 项检查、原有战斗回归、部分弹匣换弹以及姿态和时钟恢复检查通过。
第一阶段使用独立冻结输入、增强画质、90 FPS 上限,三轮每轮各 40 秒,前/后、后/前、前/后串行采样。编辑器、helper、profiler 和渲染计时查询关闭;实际绘制帧数与回调数相符,300 活体同屏更新且攻击逻辑继续运行。CPU 的 100% 表示一个逻辑核心。
| 300 只同屏,三轮中位数 | GDScript 邻居计算 | 原生邻居计算 |
|---|---|---|
| 平均 FPS | 71.60 | 72.87 |
| P99 帧时间(ms) | 22.17 | 20.36 |
| 最差完整一秒帧数 | 69 | 70 |
| 三轮 >50 ms 帧数 | 0 | 0 |
| 游戏进程树 CPU | 107.73% | 101.83% |
| 僵尸逻辑 CPU P50(ms) | 2.903 | 1.345 |
局部逻辑耗时下降约 54%,整进程 CPU 下降约 5.5%,FPS 提升约 1.8%。局部提速不能按比例外推整帧收益,P99 仍超过 16.667 ms,因此未通过严格稳定 60 FPS。
静态阴影代理合批保留相同的约 121 万个三角形,四机位 RGB 逐像素相同,但没有明确帧率收益,默认关闭。全量缓存预热另有四机位相同画面对照,但正式同屏候选约 62–67 FPS、长途一轮 P99 26.45 ms、最低一秒 35、6 帧 >50 ms,未采用。不同时间段与后台负载的差异不能用来计算精确单项成本。Vulkan 候选有管线缓存错误和长帧,取消限帧也未改善尾帧,均未采用。
本轮不重新宣称整款游戏的跨引擎排名:原生新增的任务和联机范围与 Three.js 生产版不同,上轮截图与结果仅作为既有参考;玻璃、雾和水面的实际着色差异继续保留。原始日志、私有源码、冻结工程及截图留在本机,公开文档只记录方法与汇总。保持增强画质、300 只完整实战、长途尾帧及平台功能均通过后,才进入正式迁移评估。
保留配置的独立验收
保留原生邻居计算,关闭阴影合批和全量预热。使用另一份完整冻结输入,三轮同屏各 40 秒、三趟长途各约 384 秒,均为新进程、90 FPS 上限、串行 GPU;长途每趟实际约 6.92 公里,完成相同 7.04 公里规划路线,300 活体持续更新。此组为绝对验收,不与第一阶段的不同时间窗口混算单项收益。
| 指标 | 300 只密集同屏 | 300 活体长途 |
|---|---|---|
| 平均 FPS 中位数 | 61.73 | 68.66 |
| P95 帧时间(ms) | 20.16 | 20.88 |
| P99 帧时间(ms) | 21.94 | 25.25 |
| 最差完整一秒帧数 | 60 | 27 |
| 最大帧时间(ms) | 30.21 | 315.49 |
| 三轮 >50 ms 帧数 | 0 | 3 |
| 进程树 CPU 中位数 | 92.88% | 101.19% |
| 已有缓存的新进程就绪(ms) | 9579 | 10539 |
| 最大进程树 RSS(MiB) | 1480 | 2162 |
同屏三轮为 61.51–61.85 FPS;长途三轮为 67.61–68.85 FPS,最低一秒分别为 27/46/37。六个窗口实际绘制帧数均与回调数相同,冻结输入前后 hash 不变。预先固定的最低完整一秒 ≥60、P99 ≤16.667 ms、零 >50 ms 门槛,六个窗口全部未通过,未正式迁移。不能用平均超过 60 来承诺骑行全程不卡顿。
压力窗口隐藏 HUD,不运行任务和存档,锁定生命以维持 300 活体及全部攻击/碰撞;它不是完整玩法持续存活或联机性能证明。另一段带 HUD、真实伤害和自动存档的实际任务诊断为 67.47 秒、72.49 FPS、P99 20.79 ms、最低一秒 63、零 >50 ms,4,892 个绘制与 4,891 个间隔相符,但自动骑手最终死亡;未做三轮,也没有整进程 CPU 数据,不混入正式矩阵。
两次中途停止实际绘制、回调继续的尝试拒收并保留,之后启用置顶和仅跟随测试子进程的休眠抑制,重新完整采集最终矩阵;没有只选其中较高的 73 FPS 旧窗口。macOS 后台文件同步与其他用户活动未完全隔离,315 ms 长帧尚未完成归因;GPU 计时在 Metal 上不可用,不能把 0 当成 GPU 耗时。CPU 100% 表示一个逻辑核心,就绪观察精度约半秒,缓存准备成本另计。数据只覆盖本机 M1 Pro,不代表其他平台或数小时运行。
性能矩阵冻结后另补同版本号换房时的首次插值重置,以及底部提示位置、菜单滚动和小窗口布局;计时压力模式不创建 HUD 或加入房间,功能复核使用另一个明确标识的副本。17 项真实 ENet socket 检查覆盖输入超时、版本拒绝、离开、重连及返回单人;状态恢复回归包含同版本换房,均通过。Godot AI 最终实际执行骑行、射击、近战、换弹、保存和按键读档,恢复约 16.21 米的行驶状态并释放全部输入;桌面及 390×844 菜单、Tab 焦点与滚动检查通过,不等于实体手机、触屏操作或双渲染客户端性能验收。临时检查片段的缩进与空焦点错误保留,修正后新一轮游戏日志无错误,已有静态警告未隐藏。
另一个未采用的主渲染顶点索引候选把约 996 万顶点降为 640 万,但 20 秒诊断仍只有 63.86 FPS、P99 21.70 ms,并增加约 5.22 秒启动处理。它没有完成四机位画面及三轮 A/B 验证,不作为正式优化收益或稳定 60 FPS 证明。
2026-10-15 续测:HUD 布局与连续三单
本轮用 Godot AI 社区 MCP 编写、parse 检查及实机复核;Three.js 保留为正式主版本。修正 HUD 每次读数更新触发的同步整体测量,改为尺寸、菜单打开及内容变化事件;只跳过隐藏菜单并不足以解决问题。诊断中原强制布局一次约 150ms,修复后连续 200 次轮询无重复测量。并缓存绕障排序的固定距离、共享相同立面显示条件、复用已有碰撞窗口,没有降低增强效果或敌人更新频率。
全新存档、初始 300 只、正常伤害 / 弹药 / 扫掠碰撞 / 交付条件的连续三单已完成:约 2.60km、273.18 秒骑行、164 次击杀、860 分,保存及独立进程恢复核对通过。沿用既有交付补给,未开无敌;本次路线未被近身命中,伤害 / 死亡另由战斗回归及早期死亡样本验证。此前第三单回程反复倒车的中止样本保留,采用真实院内道路绕出后重新从新档完成;恢复检查点的诊断不计作连续通关。
增强档仍为 1821×1138、4×MSAA、4096 四级 / 220m 阴影、SSAO、SSIL、48 步 SSR、光晕、水面及既有立面。90 FPS 上限、VSync 关闭、60Hz 逻辑,正式窗口串行且不带编辑器、helper 或 profiler。下表各为一个绝对验收窗口,实际绘制数与回调数相符,冻结输入前后 hash 不变。
| 场景 | FPS | P95 / P99 ms | 最低完整一秒 | >50ms | 应用 CPU | 就绪 s | RSS 峰值 MiB |
|---|---|---|---|---|---|---|---|
| 连续三单真实实战 | 77.95 | 18.36 / 20.53 | 61 | 0 | 105.36% | 10.26 | 1666.7 |
| 300 活体长途 6.92 km | 78.73 | 19.02 / 22.43 | 52 | 1 | 105.07% | 10.75 | 1718.9 |
| 300 只密集同屏 | 71.48 | 19.23 / 20.50 | 64 | 0 | 99.88% | 9.16 | 2217.7 |
三单带 HUD、自动存档和真实伤害,结束剩余 136 活体;另外两项锁血以维持 300 活体和攻击 / 碰撞压力,隐藏 HUD、不跑任务和存档,不能混称同一负载。就绪为已有资源 / 合批缓存下的进程启动观察,约 ±0.5s;本轮 Godot AI 审阅副本首次合批约 29.23s、内部 READY 37.25s,不把缓存启动当首次准备。CPU 100% 表示一个逻辑核心,统计应用进程树。
三个窗口均未完全满足最低完整一秒 ≥60、P99 ≤16.667ms、零 >50ms;稳定 60 FPS 验收仍未通过,不正式迁移。长途完成同一约 7.04km 规划、实际约 6.92km,此前约 315ms 停顿未在本轮复现,但仍有 52.108ms 长帧,不能宣布全部卡顿根因已消除。
三轮各 30 秒真实玩法短窗,前/后、后/前、前/后交替,实际每窗约 26 秒采样,保持同画质、控制及伤害并开启 HUD / 自动存档:
| 三轮短窗汇总 | 修改前 | 修改后 |
|---|---|---|
| FPS 中位数 | 66.97 | 66.68 |
| P95 ms 中位数 | 22.23 | 22.36 |
| P99 ms 中位数 | 24.03 | 29.02 |
| 应用 CPU % 中位数 | 95.89 | 97.53 |
| 最低完整一秒 | 50 | 32 |
| >50ms 合计 | 1 | 4 |
这组没有证明整机性能明显提升,修改后 P99 和长帧也未稳定改善;六窗全部保留。一次回调 2,301 / 实际绘制 28 的窗口作废,随后以前台窗口重跑并继续核对真实绘制数。局部绕障诊断中位 31.90 → 22.03ms,控制及 13 个绕行点相同,也不作为整机收益。
一个同机位增强静帧的原始 RGB 逐像素一致,另有 377 个位置 / 10,933 个立面状态对照、559 组碰撞请求及插入 / 删除 / 刷新序列一致;不能仅凭一个静帧推断全地图动态画质。Godot AI 桌面及 390×844 菜单、滚动和 Tab 焦点复核通过。44 项玩法 / 存档检查、战斗回归、6,000 个分离向量和 17 项本机 socket 回归通过;本轮没有公网 / 双窗口联机性能验收,也没有重新测 Three.js。
分离渲染线程报字体及资源释放错误,未采用。完整 Metal trace 失败,缩至一秒后虽成功记录,表导出仍未完成,不能给出可信 GPU 阶段耗时;渲染信号间隔不等于 GPU 时间。原始日志、私有源码、截图和 trace 留在本机。性能数据只对应本轮冻结版本;共享目录随后出现的分阶段启动改动保留,需另行冻结验收,未混用其源版本。本轮测试结束截图另补 CanvasItem 重绘同步,不作为新计时结果。
2026-10-15 三层反馈、骑车碰撞与踹飞
此前原型的活体没有进入骑手碰撞查询;补入沿实际世界扫掠线段的连续活体接触,倒车脱离、擦边和高度分离分别校验。Q 踹击保留 35 伤害、2.2m 距离、0.5s 冷却和墙体遮挡,加入腾空、落地及尸体飞行。不是完整刚体布娃娃,真实近身伤害保持。现有快照三维 recoil 可恢复飞行,旧格式仍可读取;联机规则指纹更新,不能混连旧规则。
1,013 项接触 / 击飞检查通过,既有伤害、换弹、遮挡、存档、17 项本机 ENet socket 检查通过。Godot AI 原生近身夹具中保持 300 活体、无无敌:一次请求前进 4m 的移动被限制到约 1.224m;真实 Q 输入使敌人生命 70→35、升高约 0.64m,同时玩家被攻击一次 100→90。夹具和截图不计作性能或全新三单样本。
尾帧诊断暂时停止反射后 P99 约 29.78→20.43ms,该降效果窗口排除验收,只说明反射是负担之一。候选保持每块水面 820×512 /20Hz 与所有增强效果,将不同水面的捕获错开。两块水面各 3s 60 次,120Hz 驱动下最大间隔 6 帧,预热后无集中在同帧的捕获;实际低帧率仍可能合并截止时间,不保证无长帧。
第一组两轮交替短窗中,P99 中位数 29.52→25.65ms,平均 FPS 约 51.5→51.7;停止的编辑器仍在场,是初筛,不能作正式加速结论。之后关闭编辑器的一对有效短窗没有重复该尾帧收益:
| 约 26 秒真实采样 | 修改前 | 反射错峰候选 |
|---|---|---|
| 平均 FPS | 39.68 | 38.59 |
| P95 / P99 ms | 36.18 / 38.89 | 35.72 / 39.17 |
| 最低完整一秒 | 37 | 33 |
| >50ms | 1 | 2 |
| 最大帧间隔 ms | 50.11 | 68.83 |
| 应用进程树 CPU | 79.11% | 80.72% |
| 已有缓存就绪 s | 10.49 | 9.30 |
| RSS 峰值 MiB | 2045.2 | 1659.1 |
初始 300、HUD / 自动存档和真实伤害开启,两窗均约 218m、57 击杀,生命 100,本短路未被命中。实际绘制与回调相差一帧;增强档 1821×1138、4×MSAA、4096 四级 /220m 阴影、SSAO / SSIL /48 步 SSR / 光晕 / 水面 / 立面保持,90 FPS 上限、VSync 关闭。CPU 100% 为一个逻辑核心,就绪观察约 ±0.5s。首次新的合批缓存仍需约 43–50s / 版,不能用缓存就绪替代;不同系统窗口分别报告,不沿用较早较高 FPS。系统后台活动未完全隔离,后测的 OS 快照不能解释每一帧。
因此未证明整体加速、CPU 降低或稳定 60 FPS。新流程在首个候选完整短窗失败后早停,连同准备约 92s;保留失败,不继续昂贵长测。本轮没有重新跑新碰撞版本的完整三单 / 长途,没有正式迁移,Three.js 保留,也没有新的跨引擎排名。
另一次只有 18 实际绘制 /517 回调的窗口拒收,不把其约 200ms 计作骑行卡顿。临时测试入口解析问题修复后通过,增加解析前检与绘制停止的提前拒收。Metal GPU profile 返回 0,记为不可用而非零 GPU 开销,不反复捕获大 trace。源码、原始日志和截图留在本机;第三层入口尚未端到端执行,不能写成验收通过。分层方法见性能手册。
反射错峰收益没有重复,当前源码默认恢复原调度,仅保留显式开发试验开关;冻结的错峰候选和所有失败数据保留。骑车碰撞 / 踹飞保留,未迁移生产。
2026-10-16 帧率回落归因复核
旧版 70 多 FPS 与后来的约 40 FPS 尚不能视作受控代码退化幅度。本轮用同一接触 / 踹飞版本、同园区任务输入、独立进程复核;没有改动画质或关闭真实战斗。以下均为约 30 秒运行、排除四秒预热后的约 26 秒完整窗口,保留失败帧。
| 同版本窗口 | FPS | P95 / P99 ms | 最低完整一秒 | >50ms | 最长帧 ms | 应用 CPU | 后台 CPU |
|---|---|---|---|---|---|---|---|
| A/A ① | 65.69 | 21.01 / 23.59 | 47 | 0 | 40.57 | 110.05% | 472.88% |
| A/A ② | 59.80 | 23.33 / 28.66 | 49 | 3 | 87.40 | 107.44% | 535.35% |
| 后续短测 ① | 68.16 | 20.28 / 23.14 | 60 | 0 | 44.45 | 105.64% | 376.35% |
CPU 100% 为一个逻辑核心。首窗全部前台,后两窗分别约一半、约 92% 的间隔被记录为失焦;即使留出采样时段,也未确保原生窗口持续前台。因此不是三轮正式 A/B,也不计算优化收益。后续第二段未产生结果文件,保留失败,不用片段补造 FPS。所有完整窗口 P99 均超过 16.667ms,稳定 60 FPS 未通过,没有继续本轮三单、长途或迁移,Three.js 保留。
增强档保持 1821×1138、4×MSAA、4096 四级 /220m 阴影、SSAO / SSIL /48 步 SSR /光晕 /水面及立面,90 FPS 上限、VSync 关闭、60Hz 逻辑。初始 300 只、真实伤害、骑手碰撞和踹飞均开启;各短窗约 217–218m /57 击杀、生命 100,不是 300 始终存活或同屏的压力样本。本路线未被近身命中,不替代完整实战验收。
同代码波动、焦点和后台负载已有同时观测证据;整机 GPU 约 96–97%,但不是游戏进程 GPU 耗时。物理 / 战斗通常几毫秒,证据更偏向渲染 / 呈现与共享设备负载,仍未锁定单个 GPU pass,也没有证明 70→40 的唯一原因。反射视口遮挡剔除诊断更慢、物理步不足,未采用;暂停反射更新或改回同步启动的诊断没有形成受控收益,亦未采用。旧版历史复跑约 77.27 FPS /P99 20.41ms,缺少新碰撞 /踹飞,只用于历史归因,不能作迁移对照。
测量工具现按真实窗口计算物理步数,记录焦点、后台 CPU /整机 GPU、采样开销与热状态,并检查新生成的静态缓存 /导入文件清单。此前清单只核对已列文件,可能遗漏首次运行的新缓存,不能据旧短测声称所有派生输入完整冻结。GPU 单项查询改为只读 IOKit 属性,本机微测中位数约 31.91→0.053ms;完整采样仍有 ps /系统等待,最新每次平均约 82.9ms,不外推游戏 FPS 收益。10 项工具回归、定向战斗 /接触 /存档 /水面检查及 Godot AI 六脚本解析检查通过,均不等于 60 FPS 验收。
本轮归因工程刻意保留 pre-Retina 输出;同期共享源码的 Retina/UI 改动未回滚,新显示版本需要独立冻结复测。原始记录和截图保留本机,公开文档不包含私有源码或原始 trace。
2026-10-16 原生窗口与受控 GPU 三轮短测
修复测试窗口前台生命周期与 Retina 二次放大后,用当前完整接触 /踹飞版本独立进程串行三轮。每轮 30 秒,排除四秒预热,保留完整约 26 秒帧数据。以下三轮版本、实际缓冲、工具、路线和二进制指纹一致;加载前 /结果写入后关闭测试窗口渲染,最近五次后台 GPU 中位数 ≤10%、峰值 ≤25%,后台 CPU 均值 ≤200%、峰值 ≤350%,逐帧焦点持续为真,三轮前后均通过。
| 轮次 | FPS | P95 / P99 ms | 最低 1s | >50ms /最长 ms | 游戏 /后台 CPU |
|---|---|---|---|---|---|
| 1 | 73.48 | 19.28 / 21.65 | 69 | 0 / 24.04 | 99.43% / 133.03% |
| 2 | 73.50 | 18.93 / 21.50 | 67 | 0 / 31.77 | 99.03% / 130.05% |
| 3 | 73.83 | 19.23 / 21.29 | 69 | 0 / 23.62 | 99.01% / 120.61% |
CPU 100% 为一个逻辑核心;应用为全线程合计,不能据约 100% 断言单个主线程满载。三轮 5738 个有效帧间隔均有焦点,P99 仍超过 16.667ms,所以稳定 60 FPS 未通过;没有继续三单、长途或迁移,Three.js 保留。
保持增强效果、3D 1821×1138 /4×MSAA,UI 原生 2880×1800;4096 四级 /220m 阴影、SSAO /SSIL /48 步 SSR /光晕 /820×512、20Hz 水面反射及完整立面。初始 300、真实伤害、骑手碰撞和踹飞逻辑保留。各窗约 217–218m /57 击杀、最终存活 243、生命 100;路线近身攻击和骑手接触计数为 0,不能替代 300 始终存活同屏或近战实战验收。接触、受击和踹飞由另外的逻辑回归覆盖。
相同当前版本、同一个无插桩入口在后台不合格时曾为 53.65 /42.33 /49.52 FPS,三次同样无失焦;后台回落后恢复到上表 73.5–73.8 FPS。这说明共享 GPU 负载是显著干扰,不能把历史约 70→40 全部归因到代码,也未证明某个后台应用是唯一来源。无游戏时的 GPU 驱动计数增量主要归于 WindowServer,只用于未公开计数的诊断排序。补充只读频率诊断:无游戏 GPU 388–417MHz、约 2.2W,频率归一化负载约 30%;游戏短诊断十次均 1296MHz /100% 活跃、约 14W,温度约 70.7–74.5°C,所采时段未见降频。高利用率不直接等于最高频率下的占用,不能外推未采到的历史热状态。
独立五秒 Metal HUD 报告将计时拆开:平均 CPU 命令缓冲编码 2.78ms、GPU 编码段 15.09ms、GPU 命令缓冲跨度 19.36ms、提交到实际显示的 Present Delay 19.19ms(0.06–40.14ms)。顶点 /片元 /compute GPU 平均 3.53 /6.53 /6.20ms。它们存在重叠,不能相加或相减冒充独占等待;诊断有 HUD、报告与截图开销,不混入上表验收。原生帧回调和实际显示也不等同。此前 CPU 渲染信号墙钟不是 GPU 时间,Godot 的本机 GPU 查询零值不再当成真实 GPU 零耗时。GPU 渲染 /呈现仍为重点,尚未唯一归因到某个未命名 pass。定义见 Apple Metal HUD 指标。
反射错峰保持每块水面相同 820×512 /20Hz 和环境效果;12 秒短筛(四秒预热)73.17 FPS /P99 18.582ms /最低秒 72,环境与焦点合格,仍未过绝对门槛,不作为正式重复 A/B 收益或长测许可,默认原调度保留。完整属性逐三角形一致的索引候选主顶点仅减少约 3.53%,其测量碰到后台负载回落,不能把 72 FPS 归功于索引,未采用默认。独立渲染线程触发纹理更新 /资源线程错误,提前拒绝,未产生有效性能结果。
Retina 错误来自 Godot 已消费 --resolution,原逻辑检测不到它又乘屏幕倍率,曾得到 UI 5760×1982、3D 1821×626;该诊断作废。现用 macOS 默认窗口尺寸,保留显式 CLI 大小。默认 /显式原生启动及缩放回归均保住 1821×1138 /4×MSAA;这是独立的新显示版本,不能直接把旧 pre-Retina 数据作受控对照。独立测试 app 只改变本地包元数据 /签名,官方二进制两种架构的数据和可执行 section 一致,原安装未改。
13 项 Python 门禁、定向接触 /战斗 /存档 /水面 /显示检查、两次原生显示回归通过;headless 不作 GPU 证据。保留后台失败、尺寸错误、受扰动诊断和候选失败记录,原始报告、截图和日志只留本机。缓存内容就绪约 6.26–6.65 秒;人工激活 /预检等待另记,不当作真实冷启动收益。新采样扰动未单独隔离,本机单人短窗不外推公网、双渲染客户端或整图长途收益。