Files
future-harmony-freeze-oom-fix/harmony-ths-futures-freeze/doc/change-notes/09-drawline-dedup-optimization.md
T

3.2 KiB
Raw Blame History

画线绘制候选集去重 O(n²) → O(n)

修复提交

仓库 分支 Commit ID 说明
hmdrawlinebasicsdk work-clz-fuhm-1979-drawline-dedup c3f8e6bc2ca44af9afa9bf0163d88d2508d55a0a 画线绘制候选集去重 O(n²)→O(n)
harmony-ths-futures work-20260818-clz-FUHM-1979-apm-appfreeze ce0719178530b5ca64272c6c1e90b5bcdb8297fc 接入 libs/drawlinebasic-1.2.1-dedup-opt.har 及主工程 overrides

问题

冻屏聚类 200202175 次)、200203403 次):主线程栈停在 DrawingApiImpl.appendUniqueLines → findIndex → isSameLinedrawLines() 每帧渲染都会调用 getLinesToDraw() 重建绘制候选集,其中 appendUniqueLinessource.forEach 嵌套 target.findIndex 判重,复杂度 O(n·m)。画线数量较多或跨周期线合并时,主线程持续繁忙触发 3S/6S 冻屏上报。

判重语义(原 isSameLine):同对象引用、本地 ID 或远端 ID 任一非空且相等即判为同一条线。注意本地 ID 不同但远端 ID 相同的两条线也判同一条,因此不能用单一 key 去重。

优化方案

  1. appendUniqueLines 改为三个 Set(对象引用 refSet、本地 ID localIdSet、远端 ID lineIdSet)一次遍历完成判重,复杂度降为 O(n);判重语义与原 isSameLine 逐条等价,目标列表插入顺序不变;原私有方法 isSameLine 随之删除。
  2. 补丁基于 hmdrawlinebasicsdk 仓库 feature-zyh-20260708-FUHM-1578-cross-period 分支(画线 SDK 1.2.1 的发布源,与 ohpm 发布包源码树逐字节一致;master 仍为 1.1.2,无此代码),仓库内 commit c3f8e6b,本地构建产物为 libs/drawlinebasic-1.2.1-dedup-opt.har
  3. 主工程三处接入:根 oh-package.json5 依赖与 overridesbiz_quote/oh-package.json5 依赖均改为 file: 引用本地 HAR。overrides 同时将 drawlinepane@1.1.0 传递依赖的 drawlinebasic@1.2.0 强制指向同一本地 HAR,保证最终产物只有一份 drawlinebasic。

影响范围

  • 仅画线绘制候选集的去重实现;画线数据模型、持久化、云端合并、绘制样式与命中逻辑不变。
  • 每帧绘制候选集重建仍会分配三个 Set,列表本身不缓存;进一步可考虑按 cache 版本缓存合并结果(本次未做)。

预期收益与边界

候选集去重由 O(n·m) 降为 O(n),画线数量越大收益越明显,直接消除该冻屏聚类的热点函数。判重语义与原实现逐条等价(含"本地 ID 不同但远端 ID 相同判同一条"的边界情形),重复描边、线条层级行为不变。画线 SDK 侧彻底根治仍建议上游将 getLinesToDraw 的合并结果按缓存版本缓存,避免每帧重建。

验证建议

  1. 执行 ./claude_tool/claude_compile.sh 编译通过。
  2. 真机在画线较多(数十条以上)的 K 线页面滑动、切换周期,确认绘制行为与改动前一致,冻屏主线程栈不再出现 appendUniqueLines → findIndex
  3. 回归跨周期画线:新建、云端合并、编辑态切换、删除场景下无重复描边,线条层级与命中结果不变。
  4. 检查最终产物中 @b2c-f/drawlinebasic 仅存在一份(overrides 生效)。