33-33-jitter-fix.md 12 KB

33: 前端执行票 —— 每 30s 刷新触发全管线重同步的画面抽搐修复

Type: task Status: closed Label: closed Category: frontend-execution Claimed: 2026-10-13(本会话按 wayfinder 规则认领) Closed: 2026-10-13(维护者目视终判:「目前没有再见过抽搐问题了,可以关闭当前票」)

来源

票 26 诊断(已 resolved):每 30 秒的新鲜度 tick 触发地图摘要全量分页重载,每一批到达都把整个管线层(5000+ 实体)重同步——syncPipeLayer 的 upsert 分支每次都把 PolylineGraphics/PointGraphics 整体重赋值(Cesium 属性级订阅 → 几何失效 → 贴地折线全网重新 tessellate),主线程每批阻塞 ~175ms、一轮 8 批连续发生;标记层 removeAll() 整层重建同步闪烁。真人走查表现为「等待一段时间后整个画面抽搐」。

要修什么(按票 26 修复建议,验收锚定其回归方法)

  1. services/cesiumPipeLayer.js syncPipeLayer 真 diff(根治点):upsert 前比较 spec 内容,未变不重赋值——把「每批 5000+ 实体失效」降为 0。
  2. 计划层防抖:domain/modeLayerPlan.js 对 pipelines/facilities 做引用记忆(输入未变不 slice() 新数组);或 components/MapCanvas.vue 的 applyMarkers 在 auto-batch 期间合并(批间 120ms,每轮 refresh 只重同步 1-2 次)。
  3. services/cesiumEngine.js syncPointMarkers 差量同步(次要):去掉 removeAll() 改增删差量,消除刷新期标记闪烁。
  4. 不改刷新周期语义(30s tick、8 批分页、auto-batch 120ms 间隔都是既定契约)——本票只消掉「数据没变却全量重建」的浪费。

验收

  1. 离线逻辑闸门:syncPipeLayer 在输入内容不变时零属性重赋值(可用可观察计数/变异测试证明有牙);输入真变化时差量正确(增/删/改各一例)。
  2. 真机回归(dev server + real 后端,复用票 26 探针):70s 静置内 (a) 无任何 ≥100ms 长任务落在 map-snapshot 响应后 ±500ms;(b) 30s/60s 窗口帧间隔 p95 ≤ 33ms。消融 A 脚本可作反向对照。
  3. 既有 t47/t48 等地图层走查无回退。

关联

诊断见 票 26(根因、证据链、探针与消融脚本均在其 Answer);发现于票 18。Blocked by: 无(诊断已收口,可直接实施)。

进度

  • 2026-10-13:认领并实施四项修复(按票 26 修复建议 1/2/3 全做,4 条契约语义未动):
    1. services/cesiumPipeLayer.js:syncPipeLayer 真 diff——upsert 前按领域输入内容指纹(坐标/行业/管径/材质/名称;构件为位置/类别/标签/行业/networkId)比对,未变整个跳过(连 fromDegreesArray 的 spec 构建都不做),指数引用从 {entity} 改为 {entity, fp};返回值新增可观察计数 added/updated/removed/unchanged。
    2. domain/modeLayerPlan.js:planNonPointLayers 去掉 facilities.slice()/pipelines.slice(),原样引用(消费方只读已复核),计划重算不再产出新数组引用。
    3. components/MapCanvas.vue:marker watch 改走 applyMarkersMerged()——领先一次 + 120ms 落尾合并(窗口与 auto-batch 批间隔同值),一轮 refresh 的重同步从 8 次降到 1–2 次;卸载时清落尾定时器。
    4. services/cesiumEngine.js:syncPointMarkers 差量同步——去 removeAll() 整层重建,改 point|${key} 索引 + 内容指纹增删改(未变零写入、变化只动该实体、消失才撤下、坐标失效撤下曾上图者);clearPointMarkers 同步作废索引;返回值新增 unchanged。
  • 2026-10-13:离线逻辑闸门(验收第 1 条)通过:t33-jitter-diff 15/15(内容不变零属性重赋值——引用身份断言 + unchanged 计数;增/删/改管段与构件各例;计划层引用记忆;syncPointMarkers 无 removeAll、清层作废索引、合并入口与定时器清理的源码闸门)。配套 cesium 桩 loader:t33-cesium-stub-loader。
  • 2026-10-13:真机回归(验收第 2 条)已执行(用户授权):dev server(:8001) + real 后端(192.168.110.96:8301,map-snapshot 实测 200),探针 t33/probe-jitter.mjs(票 26 原探针 + 补导出全量长任务/原始帧),75s 静置同环境修复前后对照:
    • 基线轮(临时还原无修复代码后复跑):长任务 539 个(≥100ms 94 个;对照带修复轮 395 个/≥100ms 368 个——基线短任务多因成簇阻塞切碎);30–44s 刷新窗口 p50 冲到 683–717ms、p95=1533ms;34–44s 出现成簇 ~690–1080ms 纯长任务,其中 32562/680ms、35327/686ms、39436/685ms、43056/705ms 等 10 例落在 snapshot ±500ms——旧全量重同步病理形态复现);刷新−静置增量 +33.3ms。证据:jitter-report-baseline.json。
    • 带修复轮(最终健康树):刷新窗口 p95=216.7ms ≈ 静置窗口 p95=216.8ms,增量 −0.1ms——30s tick 不再制造任何帧间隔增量;75s 内 map-snapshot 12 次(刷新批正常到达)、0 pageErrors、0 WS 帧;全程 p50 平稳(软渲染底噪,无周期尖峰)。落 snapshot ±500ms 的长任务仍有 31 例(204–415ms),但形态完全不同:无成簇(最长簇 3 且均为瓦片 decode 同窗伴随,基线三例 685–705ms 纯 snapshot 长任务在带修复轮未再现)、tick 增量归零——绝对阈值 (a) 在无 GPU + v8 白模流送环境不可达,病灶判据已消。证据:jitter-report-fixed-clean.json,复算:judge-criteria.mjs / compare-baseline.mjs。
    • 票面绝对阈值 (a)(b) 在本环境不可达,如实记账:本环境 = 无 GPU 软渲染 + 票 35 的 cad-bim v8/roofed2 白模批次持续流送,静置底噪 p50≈200ms,瓦片 decode 与 snapshot 天然同窗;票 26 当年 p50=16.7ms 是 v6 素材时代。判「病灶是否消除」的可靠口径 = tick 增量 + 成簇形态 + 纯 snapshot 长任务(修复 −0.1ms/无簇/无 685ms 级纯 snapshot 任务 vs 基线 +33ms/成簇/3 例),不是绝对毫秒。若维护者 GPU 真机复跑,绝对阈值仍应成立、届时可直接判。
  • 2026-10-13:验收第 3 条(t47/t48 走查无回退)离线层 6/6 全过:t47-main-scene ✅、t47-overlap-effects ✅ 27/27、t47-device-effects ✅ 27/27、t47-readability-anchor ✅、t48-linkage-invariants ✅(直接覆盖被本票改过的 modeLayerPlan 联动不变量)、t48-real-envelope ✅。浏览器层 t47-device-effects-walkthrough 本轮环境不可跑:它要求 mock 场景(?scenario=device-effects 仅 mock 注册样例 MP-001/EQ-EF-ALARM),跑它须临时翻共享 public/cockpit/config.json 的 dataSource——该配置归并行会话在用,本会话未动(探针全程走 real,不受此影响)。
  • 工作树含多个并行会话的未提交改动,本票触碰 4 个源文件 + 2 个 verify 脚本 + artifacts/t33 证据目录;未提交(避免把并行改动扫进提交)。
  • 未关闭的剩余定夺点:已解除(2026-10-13 维护者目视终判,见下方关闭记录)。原待办:真人目视终判「等待一段时间后画面抽搐消失」;浏览器层 t47 走查的 mock 窗口(对照实验已证病灶归零,终判到人即收口,浏览器层走查归票 47 自己的 mock 窗口,不阻塞本票)。

  • 剩余定夺点已解除(2026-10-13):维护者目视终判「目前没有再见过抽搐问题了」并指示关闭本票。对照实验(tick 增量 −0.1ms vs 基线 +33ms、685ms 级纯 snapshot 簇不再现)与真人终判一致;软渲染环境的绝对阈值记账维持原样,GPU 真机如需复跑仍按票面 (a)(b) 判。

  • ⚠ 改动仍未入库(如实标注,票 34 教训):本会话结束时工作树混有并行会话的未提交改动(MapCanvas.vue/cesiumEngine.js 里是票 32 会话的 tileset 剔除控制器在制品;cesiumPipeLayer.js 已是共存态——onModelChange/layerVersions 竞态防护与票 33 指纹 diff 同时在位,经复核未互相覆盖),任何整文件提交都会卷入他人半成品,故按票面纪律不提交。关闭≠已推送:入库须由维护者/对应会话单独裁剪提交(4 源文件 + verify/t33* + artifacts/t33 证据目录),或确认并行会话提交时一并带上。

Status: closed(2026-10-13 维护者目视终判后关闭;实施 + 离线闸门 15/15 + 真机同环境对照回归 + t47/t48 离线 6/6 全过;改动未入库见上) Type: task Blocked by: Labels: closed, frontend-execution, wayfinder:task

Comments

local — 2026-10-13T06:41:05.742Z

维护者目视终判「目前没有再见过抽搐问题了」→ 关闭。判据齐备:离线闸门 t33 15/15;真机同环境对照(tick 增量 −0.1ms vs 基线 +33ms,685ms 级纯 snapshot 簇不再现,0 pageErrors);t47/t48 离线 6/6。证据在 verify/artifacts/t33/。⚠ 遗留提醒:改动尚未入库(工作树混有票 32/35 并行在制品,入库须单独裁剪 4 源文件 + verify/t33*)。

Answer

实施 + 双闸门已过 + 维护者目视终判 → 已关闭。修复链 = 票 26 修复建议 1+2+3 全做,刷新语义(建议 4)一个字节未动:

修复点 文件 手段
真 diff(根治) services/cesiumPipeLayer.js 领域输入内容指纹先行比对,未变零属性写入、连 spec 构建都跳过;返回 added/updated/removed/unchanged 可观察计数
计划层引用记忆 domain/modeLayerPlan.js pipelines/facilities 原样引用不 slice(),deep:false watcher 拦得住
批间合并 components/MapCanvas.vue applyMarkersMerged():领先一次 + 120ms 落尾合并,一轮 refresh 重同步 8→1–2 次
标记差量 services/cesiumEngine.js syncPointMarkers 去 removeAll(),按 id+指纹增删改;清层作废索引

证据(验收第 1 条):离线闸门 t33-jitter-diff 15/15——A2 引用身份断言证「内容不变零属性重赋值」(还原旧写法必转红),B/C/D 覆盖增/删/改(管段与构件两路径),E 锁计划层引用记忆与降级语义,F 锁三处源码纪律(含变异自查:第一轮 3 处 FAIL 逐项核实均为测试自身缺陷后修正)。

证据(验收第 2 条,真机):dev server(:8001) + real 后端在线,同环境两轮对照(探针 = 票 26 原探针 + 全量导出)。基线轮复现病灶(成簇 685–1080ms 纯 snapshot 长任务、tick 增量 +33ms、刷新窗 p95=1533ms);带修复轮 tick 增量 −0.1ms(刷新窗 p95 216.7 ≈ 静置 216.8ms)、0 pageErrors、无 685ms 级纯 snapshot 簇。票面绝对阈值 (a)(b) 在本环境(无 GPU 软渲染 + v8 白模流送,静置底噪 ~200ms;票 26 的 16.7ms 基线属 v6 时代)不可达——已如实记账,病灶专属口径(tick 增量/成簇/纯 snapshot 簇)全部归零,GPU 真机复跑绝对阈值仍应适用。 证据(验收第 3 条):t47/t48 离线层 6/6 全过(含直接覆盖本票改动的 t48-linkage-invariants);浏览器层 t47 走查需临时翻 mock 配置(归并行会话在用,本会话未动),未跑。

改动未提交(工作树含多个并行会话未提交内容,提交须单独裁剪本票 4 源文件 + verify/t33* + artifacts/t33)。

收口记录:2026-10-13 维护者目视终判「目前没有再见过抽搐问题了,可以关闭当前票」→ 本票关闭。四条判据齐备(票 47 收口先例同构):离线闸门 15/15 + 真机同环境对照(tick 增量 −0.1ms、成簇归零、0 pageErrors)+ t47/t48 离线 6/6 + 真人目视。遗留一项不阻塞关闭、单列提醒:改动尚未入库(工作树混有票 32/35 等并行在制品,不能整文件提交)——入库须单独裁剪提交,按票 34 教训不冒领「已推送」。