Files
MapLibreParticleLab/docs/20_调查/Particle_V13_严格代码审查报告_v1.md
tei 45c4dca849
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
docs: archive independent Particle V13 code review
2026-09-25 18:52:06 +09:00

9.6 KiB
Raw Permalink Blame History

Particle V13 严格代码审查报告

日期:2026-09-25(Asia/Tokyo) 审查性质:Mac 仓库只读代码审查、历史任务/报告交叉核对、定向原生测试复跑。未修改业务源码、未执行设备 GPU runtime 或 profiler。

1. 审查基线和证据分级

  • Mac:/Users/tei/dev/MapLibreParticleLab;分支:particle/main。
  • HEAD 与 origin/particle/main 一致:ee0b89e711bf01335b3aa71d36def785cd97fec3;工作树 clean。
  • V13 功能提交:016fd1fff6a33cf795c10d4f5c5413d308383677。发布版本:13.4.1-particle.13。
  • Integration 主线:39ad8415fbdb76c1822460bb09f3a3f35fe141e0。
  • 参照:docs/40_任务/STEP-092...、STEP-093...、STEP-094... 任务;对应 docs/报告/ 与 docs/50_Step记录/;STEP-088/089/090 性能历史报告。
  • 本次独立复跑:Render Segment/Retained/Fast Path 43/43 PASS;Field/QBIN/Viewport Reseed 69/69 PASS;V13 RN package TypeScript PASS。
  • 当前 RN Test Host npm run typecheck 失败(exit 2):TS2307 无法解析 @navsea/maplibre-particle-rn,伴随 TS7006。Host package.json 仍指向 .10。此前 Codex 使用临时工作树依赖通过,不等于当前默认安装可重复验证。
  • STEP-094 报告记录 OpenGL、Metal 构建、Codegen、Android Validation APK 通过;Android/iOS V13 runtime、GPU frame/visual、功耗与长时间运行仍 NOT RUN。此报告不将历史 Android 性能测量冒充 V13 性能。

2. 审查结论

没有在已复跑的纯数据结构/协议测试中发现失败;但 V13 在高频渲染、Metal 多段重建、GPU 资源分配和真实运行态验收上存在明确风险。不能由 43 项纯 Native 测试和编译 PASS 推断任意 R/C 交错的 GPU 输出、跨平台性能已经验收。

F01 — P1:完整 Diagnostics 深复制进入每帧热路径(源码确定)

证据:src/mbgl/renderer/renderer_impl.cpp:206-208,500-505;src/mbgl/renderer/retained_underlay_runtime_state.hpp:243-254。

tryRenderParticleFastFrame() 和 render() 调用 renderSegmentSnapshot();该函数在互斥锁内复制完整 RenderSegmentDiagnostics(含 styleLayers 与每个 Segment 的重复 layers/字符串),再补几个状态字段。一次 fast frame 可能复制两次。与 pull-based 诊断的设计意图不一致。

修复:增加只读的轻量 hot-path 状态(enabled/configRevision/topologyRevision 等);完整快照只在外部 pull 时构造;快照构建/复制次数做计数,稳定 30/60 FPS 应接近零。

F02 — P1:Metal Retained 构建逐段 GPU 同步等待(源码确定,运行影响待 profile)

证据:renderer_impl.cpp:790-824;retained_underlay_cache.cpp:316-322;src/mbgl/mtl/command_encoder.cpp:29-31;src/mbgl/mtl/offscreen_texture.cpp:86-91。

finishBuild()->present(*offscreenTexture)->swap() 内部 commit() 后 waitUntilCompleted()。一帧多个 Retained 段失效时,可能产生多次串行 CPU/GPU 同步。使用 Metal System Trace / GPU Capture 测量 waitUntilCompleted 时间和 command-buffer 数量,再设计保持依赖顺序的异步提交/跨 pass 协调;不可仅删除 wait 而不确保纹理可读。

F03 — P1:缓存内容失效与 GPU 资源销毁耦合(源码确定)

证据:retained_underlay_cache.cpp:203-209,241-255,364-374。

revisionChanged 使 invalidate() 与 releaseResources() 一起发生,即使 viewport 未变、GPU context 有效,重建时仍需重新创建纹理和 composite group。普通 camera、source/tile、content revision 在多 Retained 段下会放大分配/销毁和相关同步。

修复:分离 contentDirty 与 resourceInvalid,同尺寸同 context 保留 allocation、重新 clear/build;context loss、尺寸不兼容、显式关闭/释放时才销毁。用 peak GPU bytes、textureCreate、resourceRelease、每帧 build/reuse 证明收益与正确性。

F04 — P1:多缓存没有 GPU 内存预算(源码确定,OOM 影响待量化)

证据:renderer_impl.cpp:506-524;retained_underlay_cache.cpp:241-251;mtl/offscreen_texture.cpp:20-55;gl/offscreen_texture.cpp:18-35。

每个 Retained Segment 均拥有完整 viewport 的 RGBA + depth/stencil 离屏资源;总成本约随 retainedCount×width×height 增长。相邻 R-R 也各自独立,符合契约,但高像素 iPad 与多段场景缺乏实际 bytes/peak/budget 观测。先增加预算与失败时的安全 full-render fallback,切勿通过强制合并相邻 R-R 破坏 V13 契约。

F05 — P1:V13 Test Host 默认安装不可复现(已复现失败)

证据:integration/react-native/MapLibreParticleRNTestHost/package.json 指向 .10;当前 npm run typecheck exit 2;报告也明确临时本地替换后已恢复旧依赖。

修复:将 Test Host 依赖和 lockfile 与已发布 .13 精确对应,重新安装并验证 V13 typecheck/codegen/iOS & Android bridge/真实运行;测试日志注明源包及 Native 精确版本。不得将临时链接环境结果写成默认环境 PASS。

F06 — P1:多 Continuous 的 Particle Fast Path 固定 fallback(明确设计限制)

证据:renderer_impl.cpp:45-57,198-287 和 particle_fast_path.hpp:110-140,STEP-094 设计与报告。

N 个 Continuous 中只支持恰好一个的 Fast Path;R-C-R-C-R 场景总走 Full CPU。STEP-090 历史 A/B 场景 RenderThread 约为 fast ON 21.7% / OFF 97.0%,只是历史参考,不能直接视作 V13 数据。先采集 V13 多 C 的 CPU/GPU 帧时间与频率,再设计可组合的 multi-C fast path;绝不可为性能偷偷移动 Style Layer 或合并相邻段。

F07 — P2:范围访问反复计算线性 ordinal(源码确定)

证据:src/mbgl/renderer/render_orchestrator.hpp:156-180,std::distance(multimap.begin(), lower_bound(...))。每个 Segment 的 opaque/translucent、build、upload/tweaker 路径可重复触发定位。

修复:在 LayerGroup topology 变化时预计算有序索引/ordinal;高频 render 只用稳定区间和 ordinal,避免多段场景重复 O(N) 前缀遍历。

F08 — P2:多段失效粒度仍过宽(明确设计限制)

证据:renderer_impl.cpp:565-646;render_orchestrator.cpp:156-158,1005-1018。Layer Impl fingerprint 可局部失效;source/tile/image/glyph/placement 与聚合 retainedSupported 仍可能使全部 R fallback/build。应先用 sourceId 与 Segment 关联建立有证据的保守依赖关系,无法归属继续全局失效,不得牺牲安全。

F09 — P2:Diagnostics 资源指标可能发生归属偏差(源码路径风险)

证据:retained_underlay_runtime_state.hpp:173-240 更新新 topology/entry;renderer_impl.cpp:506-524 随后 clear() 旧 caches;旧对象析构在 retained_underlay_cache.cpp:364-374 用旧 segmentIndex 报 release。不同 topology 的相同 index 可能指向新段,旧资源的释放计数可能归于新段或被 Continuous cache=null 丢弃。建议使用 cache generation/unique ID 归属,或在更换 diagnostics topology 前记录旧 generation 的 release;聚合 totals 与 per-generation 分离。

F10 — P2:发布与协调状态资料漂移(核对事实)

Integration 的 status/、compatibility/MATRIX.md 仍描述 .5 / iOS XCFramework 等旧状态,Mac 粒子仓库已发布 .13。应由粒子负责人维护正式兼容矩阵,区分“Particle 已发布”和“NavSea 已接入/验证”,不得仅根据旧矩阵断言 V13 不存在或已在 NavSea 生效。

3. 正确性与验证缺口

以下不是已证实的渲染 bug,而是必须在设备上验证的风险:

  • V13 segmented pass 改变了 opaque/translucent、offscreen composite 的执行拆分;纯 resolver GTest 不覆盖 GPU blending/depth/stencil 与 Metal/OpenGL 的最终像素。
  • 必须覆盖 R-C-R、C-R-R、R-R-C、R-C-R-C-R、相邻 R-R 独立 cache、全 R、全 C,特别是透明航标/半透明颜色场与动态粒子叠加。
  • hidden boundary、invalid/recovery、Style layer insert/remove/reorder、Resize/Rotate/Pan/Zoom/Pitch、Context loss、Cache ON/OFF、Source/Tile mutation、切换 Plan 后的下一帧,均需要截图/帧采样和资源 counter 交叉验收。
  • STEP-093/094 报告已明确运行态 NOT RUN,因此不以原生编译 PASS 代替此项。

4. 推荐执行顺序(分批,降低反复安装成本)

A. 无需设备的修复:先处理 F01 快照深复制、F05 Test Host 精确版本与复现、F07 ordinal、F09 诊断归属;增加纯 C++ 定向回归。每阶段只做对应范围,不把源文件无关改动混入。

B. Metal 资源修复:合并 F02/F03/F04,统一处理 GPU 对象分配与同步、资源预算;OpenGL/Metal 静态编译和 Native regression 先行;再一次集中到 iPhone/iPad 采集 GPU Frame Capture。

C. 正式运行态验收:集中执行 topology、alpha/depth、invalid/recovery、30/60 FPS、稳定/变更、内存峰值、30 分钟以上长稳态;记录相同设备、相同 Style、相同视口的 V12/V13 或 V13 ON/OFF 成对指标,不外推历史数字。

D. 后续性能架构:在基础正确性通过后,再研究多 Continuous Fast Path 和 source-to-segment 精确依赖。保持 Style Z-order 唯一顺序源、不合并同策略相邻段、不引入业务频率分类。

5. 最终判定边界

  • 纯 Native tests:43/43 + 69/69 PASS;RN V13 package TS PASS。
  • Test Host 默认环境:FAIL(缺失模块 / .10 引用)。
  • 源码性能问题:F01/F02/F03/F07 的触发调用链得到静态确认;真实节省量仍需设备测量。
  • V13 Android/iOS GPU runtime、完整画面、内存和长时间性能:本次 NOT RUN;不声称生产级全量 PASS。
  • Mac Git:HEAD 与 origin 一致,工作树 clean;未修改粒子源码。