perf(particle): skip repeated field snapshot deep comparisons
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
This commit is contained in:
35
docs/50_Step记录/STEP-109_V23_CPU_FieldSnapshot深比较快路_v1.md
Normal file
35
docs/50_Step记录/STEP-109_V23_CPU_FieldSnapshot深比较快路_v1.md
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# STEP-109 V23 CPU FieldSnapshot 深比较快路 v1
|
||||||
|
|
||||||
|
日期:2026-10-10(JST)
|
||||||
|
状态:进行中(源码已改;Mac Native 编译及设备 CPU 对照待验)
|
||||||
|
|
||||||
|
## 基线
|
||||||
|
- 设备:Mac.lan,仓库 /Users/tei/dev/MapLibreParticleLab。
|
||||||
|
- 分支:particle/main;起点 HEAD:5b8bdfbfbb4263fe12a060e77bc310cf77f27d61;起点工作区干净。
|
||||||
|
- 已发布基线:Android / RN 13.6.1-particle.23,iOS 6.29.0-particle.23;正式 V23 Tag、Source Lock 及制品均保持不变。
|
||||||
|
- V21 FZG1-2 曾有天气持续运行高 CPU 与疑似浮点数组比较样本;不是 V23 的测量结果。
|
||||||
|
|
||||||
|
## 调查依据
|
||||||
|
- render_particle_validation_layer.cpp 稳定每帧通过 sameFieldGpuEndpoint() 比较 T0/T1,比较包含整个 vector 与 valid。
|
||||||
|
- render_weather_color_layer.cpp 稳定每帧通过 sameFieldGpuContent() 比较完整 scalar/vector/valid。
|
||||||
|
- V23 源码中已保留 STEP-090 Fast Path;STEP-102/106 已处理部分 RenderSegment Placement 语义,不对 V23 再次假设 cache-invalid。
|
||||||
|
|
||||||
|
## 本次非正式修改
|
||||||
|
- [x] ParticleGpuResources 记录与真实 GPU T0/T1 槽位相应的 shared_ptr<const ParticleFieldSnapshot>。
|
||||||
|
- [x] WeatherColor Resources 同样记录两帧快照身份。
|
||||||
|
- [x] 相同不可变 shared_ptr 且资源代际未变时,跳过 O(N) 深比较。
|
||||||
|
- [x] 新快照对象、窗口更换、旧资源不存在时保留严格内容/端点对比。
|
||||||
|
- [x] 只有真实纹理安装成功或严格等价比较后更新资源绑定身份;clear、context loss 与资源重建自动丢弃旧身份。
|
||||||
|
- [x] 保留 T0/T1、MIX、时间跳转、窗口重用、编码/内容身份、双平台 Renderer 语义。
|
||||||
|
- [x] 未改公共 API、RN、JS/TS、RenderSegment 安全 Gate、任何发行制品。
|
||||||
|
|
||||||
|
## 构建与验收
|
||||||
|
- [x] git diff --check PASS;只修改 2 个 C++ 文件。
|
||||||
|
- [ ] Mac Metal Native Core 编译:**NOT COMPLETED / 用户验收前主动中止**。`bazel build -c opt --//:renderer=metal //:mbgl-core` 因触发 649 个通用 Core actions 的大量重编译,尚未走到构建成功/失败结论;已中断 Bazel 客户端并核对其 PID 退出。日志 /tmp/maplibre_step109_cpu_field_identity_bazel_20261010.log。此项不能写为 PASS。
|
||||||
|
- [ ] C++ directed regressions(snapshot identity、new-object differing payload、window shift、clear/reload)。
|
||||||
|
- [ ] Android OpenGL / FZG1-2 同场景 V23 原版与修改版 CPU A/B:尚未执行。
|
||||||
|
- [ ] iOS Metal iPad 实际天气场/时间窗回归:尚未执行。
|
||||||
|
- [ ] 真实性能目标:至少比较相同场数据、帧率、图层与设备条件下的平均进程、RenderThread、JS CPU;同时检查 FieldTextureUpload / SimulationReset 计数无异常增加。
|
||||||
|
|
||||||
|
## 交付边界
|
||||||
|
本 Step 不创建新发行版本,不覆盖不可变 V23 产物。代码验证成功后依当前 Git 规范 scoped commit / push;正式使用须另立版本、执行 GSRL Source Lock、SHA-256、接收验收。若编译失败,则先记录错误并修复,不得宣称优化 PASS。
|
||||||
38
docs/报告/STEP-109_V23_CPU_FieldSnapshot深比较快路_RDC阶段报告_v1.md
Normal file
38
docs/报告/STEP-109_V23_CPU_FieldSnapshot深比较快路_RDC阶段报告_v1.md
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# STEP-109 V23 CPU FieldSnapshot 深比较快路 — RDC 阶段报告 v1
|
||||||
|
|
||||||
|
日期:2026-10-10(JST)
|
||||||
|
结论:**PARTIAL / 开发态**。已针对 V23 源码热点实施局部修正;尚无 V23 真机 CPU 改善证据。
|
||||||
|
|
||||||
|
## 1. 基线
|
||||||
|
- 仓库:Mac /Users/tei/dev/MapLibreParticleLab,particle/main。
|
||||||
|
- 起点:5b8bdfbfbb4263fe12a060e77bc310cf77f27d61,起点工作区干净。
|
||||||
|
- 正式已发布 V23:13.6.1-particle.23(Android/RN)、6.29.0-particle.23(iOS);发行 Tag、Source Lock、制品均未变更。
|
||||||
|
- NavSea Mac V23 集成 checkout 为 /Users/tei/dev/NavSea-Build;Windows D:\React\NavSea 当前仍引用 13.4.1-particle.21,且有多项其他工作区修改。本轮未改 NavSea。
|
||||||
|
|
||||||
|
## 2. V23 实际源码发现
|
||||||
|
- render_particle_validation_layer.cpp 每帧调用 sameFieldGpuEndpoint() 校验既有 T0/T1,内部逐项比较 vector 和 valid。
|
||||||
|
- render_weather_color_layer.cpp 每帧调用 sameFieldGpuContent(),内部比较 scalar/vector/valid。
|
||||||
|
- 两条判断在 immutable T0/T1 未改变时仍可执行 O(N) 深比较。
|
||||||
|
- STEP-090 Fast Path 存在;STEP-102/106 RenderSegment Placement 局部修复已有 FZG 定向证据,因此不能直接照搬 V21 cache-invalid 诊断。
|
||||||
|
- V21 93.8% CPU 与 simpleperf 浮点数组采样仅为历史方向提示,不能归因于此次代码或称为 V23 基线。
|
||||||
|
|
||||||
|
## 3. 已实施代码
|
||||||
|
- src/mln/renderer/layers/render_particle_validation_layer.cpp:资源绑定持有 T0/T1 不可变快照 shared_ptr;当前资源已验证同一快照时 O(1) 判等,新对象仍严格核对内容。
|
||||||
|
- src/mln/renderer/layers/render_weather_color_layer.cpp:WeatherColor 纹理同样记录 Source 快照身份;相同内容的新对象仍使用原严格比较及资源复用。
|
||||||
|
- 全部身份绑定只在纹理准备成功或内容等价验证后建立;资源销毁、重新创建与 context loss 均自然清除。
|
||||||
|
- 未改 RN 对外 API、风场 canonical contract、T0/T1 mix、Runtime Field Window、粒子数量、GPU 纹理算法及 RenderSegment 安全回退。
|
||||||
|
|
||||||
|
## 4. 验证与限制
|
||||||
|
- scoped git diff --check:**PASS**。
|
||||||
|
- Mac Metal Core:**INTERRUPTED / NOT COMPLETED / NOT PASS**。执行 `bazel build -c opt --//:renderer=metal //:mbgl-core` 触发 649 actions 的通用 Native 重编译;基于本轮仅两文件微调、尚未安排设备验收,主动中止以控制开发成本。原远程 session 8049 和 Bazel PID 8350 均已停止;未取得构建最终通过或编译错误结论。日志:`/tmp/maplibre_step109_cpu_field_identity_bazel_20261010.log`。
|
||||||
|
- Android 用户手工编译/安装、OpenGL 实机、iOS 实机、性能同屏 A/B、全量定向测试:**NOT RUN**。
|
||||||
|
- 没有测得实际 CPU 下降百分比;本次不生成正式发行版,不覆盖 V23 Tag 或 Source Lock。
|
||||||
|
|
||||||
|
## 5. 后续验收门槛
|
||||||
|
1. Native 编译通过并定向执行现有 Field GPU / Timeline / Source 测试。
|
||||||
|
2. Android FZG1-2 以相同天气输入和粒子设置、相同 Layer stack、同一 BuildType 做 V23 原版与修正版 A/B,采样进程、RenderThread、JS,并检查 FieldTextureUpload/SimulationReset。
|
||||||
|
3. 时间切换、T0/T1 重叠窗口、clear/reload/context loss、切层、地图平移与关闭天气后恢复,在 Android/iOS 分别核对画面正确、无旧场、无多余纹理重建。
|
||||||
|
4. 用户验收后,再新建发行版本,按 GSRL 发布不可变制品与 SOURCE_LOCK.json。
|
||||||
|
|
||||||
|
## 6. Git
|
||||||
|
代码和本阶段文档暂未提交/推送,待编译结果明确后遵循 scoped commit,保存完整 hash、push 回读;不得提交任何无关修改。
|
||||||
@@ -391,6 +391,10 @@ public:
|
|||||||
gfx::Texture2DPtr stateTexture;
|
gfx::Texture2DPtr stateTexture;
|
||||||
particle::ParticleFieldSnapshot field;
|
particle::ParticleFieldSnapshot field;
|
||||||
particle::ParticleFieldSnapshot nextField;
|
particle::ParticleFieldSnapshot nextField;
|
||||||
|
// Provenance of the immutable Source snapshots currently bound to the GPU slots.
|
||||||
|
// Holding strong references makes pointer identity safe across allocations.
|
||||||
|
std::shared_ptr<const particle::ParticleFieldSnapshot> boundSourceT0;
|
||||||
|
std::shared_ptr<const particle::ParticleFieldSnapshot> boundSourceT1;
|
||||||
std::shared_ptr<style::RasterArrayTimelineRuntime> timeline;
|
std::shared_ptr<style::RasterArrayTimelineRuntime> timeline;
|
||||||
std::shared_ptr<PremultipliedImage> fieldImage;
|
std::shared_ptr<PremultipliedImage> fieldImage;
|
||||||
std::shared_ptr<PremultipliedImage> nextFieldImage;
|
std::shared_ptr<PremultipliedImage> nextFieldImage;
|
||||||
@@ -1379,6 +1383,10 @@ void RenderRasterParticleLayer::update(gfx::ShaderRegistry& shaders,
|
|||||||
Log::Error(Event::Render, "ParticleField: fixture load failed: " + std::string(error.what()));
|
Log::Error(Event::Render, "ParticleField: fixture load failed: " + std::string(error.what()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (formalSource) {
|
||||||
|
owned->boundSourceT0 = sourceField;
|
||||||
|
owned->boundSourceT1 = sourceNextField;
|
||||||
|
}
|
||||||
gpuResources = std::move(owned);
|
gpuResources = std::move(owned);
|
||||||
resources = gpuResources;
|
resources = gpuResources;
|
||||||
Log::Info(Event::Render,
|
Log::Info(Event::Render,
|
||||||
@@ -1488,9 +1496,15 @@ void RenderRasterParticleLayer::update(gfx::ShaderRegistry& shaders,
|
|||||||
" fullParticleDraw=true resourceGeneration=" + std::to_string(resources->generation));
|
" fullParticleDraw=true resourceGeneration=" + std::to_string(resources->generation));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Source snapshots are immutable. A snapshot already proven to back this
|
||||||
|
// resource generation needs no repeated O(grid cell count) payload compare.
|
||||||
|
// New snapshot objects still use the strict endpoint comparison, including
|
||||||
|
// generation, validTime, encoding, vector and validity bytes.
|
||||||
const bool sourceChanged = formalSource && sourceField && sourceNextField &&
|
const bool sourceChanged = formalSource && sourceField && sourceNextField &&
|
||||||
(!particle::sameFieldGpuEndpoint(resources->field, *sourceField) ||
|
!((resources->boundSourceT0 == sourceField ||
|
||||||
!particle::sameFieldGpuEndpoint(resources->nextField, *sourceNextField));
|
particle::sameFieldGpuEndpoint(resources->field, *sourceField)) &&
|
||||||
|
(resources->boundSourceT1 == sourceNextField ||
|
||||||
|
particle::sameFieldGpuEndpoint(resources->nextField, *sourceNextField)));
|
||||||
if ((!formalSource && resources->fixtureMode != fixtureMode) || sourceChanged) {
|
if ((!formalSource && resources->fixtureMode != fixtureMode) || sourceChanged) {
|
||||||
try {
|
try {
|
||||||
const auto oldT0 = resources->field;
|
const auto oldT0 = resources->field;
|
||||||
@@ -1613,6 +1627,12 @@ void RenderRasterParticleLayer::update(gfx::ShaderRegistry& shaders,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Record provenance only after successful GPU slot setup (or strict
|
||||||
|
// content equality); failures never bless an unverified snapshot.
|
||||||
|
if (formalSource && sourceField && sourceNextField) {
|
||||||
|
resources->boundSourceT0 = sourceField;
|
||||||
|
resources->boundSourceT1 = sourceNextField;
|
||||||
|
}
|
||||||
// Keep the shared Core runtime alive in the per-frame drawable tweaker.
|
// Keep the shared Core runtime alive in the per-frame drawable tweaker.
|
||||||
// This is a pointer to Source-owned state, not a second timeline.
|
// This is a pointer to Source-owned state, not a second timeline.
|
||||||
resources->timeline = sourceTimeline;
|
resources->timeline = sourceTimeline;
|
||||||
|
|||||||
@@ -83,6 +83,9 @@ struct Resources {
|
|||||||
SegmentVector segments;
|
SegmentVector segments;
|
||||||
particle::ParticleFieldSnapshot t0;
|
particle::ParticleFieldSnapshot t0;
|
||||||
particle::ParticleFieldSnapshot t1;
|
particle::ParticleFieldSnapshot t1;
|
||||||
|
// Immutable Source provenance for the uploaded color textures.
|
||||||
|
std::shared_ptr<const particle::ParticleFieldSnapshot> boundSourceT0;
|
||||||
|
std::shared_ptr<const particle::ParticleFieldSnapshot> boundSourceT1;
|
||||||
std::shared_ptr<PremultipliedImage> image0;
|
std::shared_ptr<PremultipliedImage> image0;
|
||||||
std::shared_ptr<PremultipliedImage> image1;
|
std::shared_ptr<PremultipliedImage> image1;
|
||||||
gfx::Texture2DPtr texture0;
|
gfx::Texture2DPtr texture0;
|
||||||
@@ -293,8 +296,11 @@ void RenderWeatherColorLayer::update(gfx::ShaderRegistry& shaders,
|
|||||||
Event::Render,
|
Event::Render,
|
||||||
"WeatherColorLayer: event=WEATHER_COLOR_FIELD_READY T0=" + state->t0.fieldID + " T1=" + state->t1.fieldID +
|
"WeatherColorLayer: event=WEATHER_COLOR_FIELD_READY T0=" + state->t0.fieldID + " T1=" + state->t1.fieldID +
|
||||||
" valueSource=" + (valueSource == style::FieldValueSource::Scalar ? "SCALAR" : "VECTOR_MAGNITUDE"));
|
" valueSource=" + (valueSource == style::FieldValueSource::Scalar ? "SCALAR" : "VECTOR_MAGNITUDE"));
|
||||||
} else if (state->valueSource != valueSource || !same(state->t0, *sourceField) ||
|
} else if (state->valueSource != valueSource ||
|
||||||
!same(state->t1, *sourceNextField)) {
|
!(state->boundSourceT0 == sourceField || same(state->t0, *sourceField)) ||
|
||||||
|
!(state->boundSourceT1 == sourceNextField || same(state->t1, *sourceNextField))) {
|
||||||
|
// The bound immutable snapshot is already verified for these textures.
|
||||||
|
// Only new snapshot objects require the O(grid cell count) comparison.
|
||||||
const auto old0 = state->t0;
|
const auto old0 = state->t0;
|
||||||
const auto old1 = state->t1;
|
const auto old1 = state->t1;
|
||||||
auto install = [&](const particle::ParticleFieldSnapshot& wanted,
|
auto install = [&](const particle::ParticleFieldSnapshot& wanted,
|
||||||
@@ -339,6 +345,10 @@ void RenderWeatherColorLayer::update(gfx::ShaderRegistry& shaders,
|
|||||||
Event::Render,
|
Event::Render,
|
||||||
"WeatherColorLayer: event=WEATHER_COLOR_FIELD_READY T0=" + state->t0.fieldID + " T1=" + state->t1.fieldID);
|
"WeatherColorLayer: event=WEATHER_COLOR_FIELD_READY T0=" + state->t0.fieldID + " T1=" + state->t1.fieldID);
|
||||||
}
|
}
|
||||||
|
// Bind provenance only after both textures are valid or their content has
|
||||||
|
// been strictly verified. Clearing or losing the context destroys Resources.
|
||||||
|
state->boundSourceT0 = sourceField;
|
||||||
|
state->boundSourceT1 = sourceNextField;
|
||||||
const float mix = sourceTimeline ? timelineFrame.mix : (sourceUsesV4Projection ? sourceProjectionMix : 0.0f);
|
const float mix = sourceTimeline ? timelineFrame.mix : (sourceUsesV4Projection ? sourceProjectionMix : 0.0f);
|
||||||
const float opacity = static_cast<const style::WeatherColorLayer::Impl&>(*baseImpl).opacity;
|
const float opacity = static_cast<const style::WeatherColorLayer::Impl&>(*baseImpl).opacity;
|
||||||
state->mix = mix;
|
state->mix = mix;
|
||||||
|
|||||||
@@ -1101,3 +1101,10 @@ Android V3-08 单次综合验收已完成并关闭。Native `13.4.1-particle.2`
|
|||||||
- build、publish、finalize 三阶段严格串行 exit 0;独立验证六项公网 SHA-256 全 PASS;SwiftPM Tag/校验值与 Git 正式发行 Tag 远端回读 PASS。
|
- build、publish、finalize 三阶段严格串行 exit 0;独立验证六项公网 SHA-256 全 PASS;SwiftPM Tag/校验值与 Git 正式发行 Tag 远端回读 PASS。
|
||||||
- 构建源码 87f3d1c59a52581fb8339f0ea7d106b9f4b94fef;发行 Tag maplibre-particle/rn/13.6.1-particle.23 保持指向 a0a4787b4379ab2819943d20ce05a7ae760a88c3。
|
- 构建源码 87f3d1c59a52581fb8339f0ea7d106b9f4b94fef;发行 Tag maplibre-particle/rn/13.6.1-particle.23 保持指向 a0a4787b4379ab2819943d20ce05a7ae760a88c3。
|
||||||
- STEP-107 XCTest、iPad 崩溃事故实机重放以及 V23 运行时集成 NOT_TESTED,不冒充设备 PASS。
|
- STEP-107 XCTest、iPad 崩溃事故实机重放以及 V23 运行时集成 NOT_TESTED,不冒充设备 PASS。
|
||||||
|
|
||||||
|
|
||||||
|
### 2026-10-10 STEP-109 V23 CPU / FieldSnapshot 身份快路(开发态)
|
||||||
|
|
||||||
|
- 对 Mac particle/main 正式 V23 源码只读核查发现:Particle 与 WeatherColor Renderer 对稳定的 Source T0/T1 仍可能在每帧执行 vector/valid 全数组比较;V21 FZG 热点仅作方向依据,不冒充 V23 实测。
|
||||||
|
- 在两个 Native Renderer 文件内保存与 GPU 资源对应的不可变 shared_ptr 快照身份;同一已验证快照用 O(1) 身份判断,新对象仍走严格数据/端点比较。未修改 RN API、RenderSegment Gate 或已发行 V23 产物。
|
||||||
|
- 本轮 git diff --check PASS;Mac Metal Core opt 编译触发 649 actions 大量重编译,主动中止且核验 Bazel PID 已退出,故编译 NOT COMPLETED / NOT PASS;Android/iOS 性能 A/B 尚未取得。阶段记录:docs/50_Step记录/STEP-109_V23_CPU_FieldSnapshot深比较快路_v1.md;报告:docs/报告/STEP-109_V23_CPU_FieldSnapshot深比较快路_RDC阶段报告_v1.md。
|
||||||
|
|||||||
Reference in New Issue
Block a user