3.2 KiB
3.2 KiB
画线绘制候选集去重 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 |
问题
冻屏聚类 20020217(5 次)、20020340(3 次):主线程栈停在 DrawingApiImpl.appendUniqueLines → findIndex → isSameLine。drawLines() 每帧渲染都会调用 getLinesToDraw() 重建绘制候选集,其中 appendUniqueLines 用 source.forEach 嵌套 target.findIndex 判重,复杂度 O(n·m)。画线数量较多或跨周期线合并时,主线程持续繁忙触发 3S/6S 冻屏上报。
判重语义(原 isSameLine):同对象引用、本地 ID 或远端 ID 任一非空且相等即判为同一条线。注意本地 ID 不同但远端 ID 相同的两条线也判同一条,因此不能用单一 key 去重。
优化方案
appendUniqueLines改为三个 Set(对象引用refSet、本地 IDlocalIdSet、远端 IDlineIdSet)一次遍历完成判重,复杂度降为 O(n);判重语义与原isSameLine逐条等价,目标列表插入顺序不变;原私有方法isSameLine随之删除。- 补丁基于
hmdrawlinebasicsdk仓库feature-zyh-20260708-FUHM-1578-cross-period分支(画线 SDK 1.2.1 的发布源,与 ohpm 发布包源码树逐字节一致;master 仍为 1.1.2,无此代码),仓库内 commitc3f8e6b,本地构建产物为libs/drawlinebasic-1.2.1-dedup-opt.har。 - 主工程三处接入:根
oh-package.json5依赖与overrides、biz_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 的合并结果按缓存版本缓存,避免每帧重建。
验证建议
- 执行
./claude_tool/claude_compile.sh编译通过。 - 真机在画线较多(数十条以上)的 K 线页面滑动、切换周期,确认绘制行为与改动前一致,冻屏主线程栈不再出现
appendUniqueLines → findIndex。 - 回归跨周期画线:新建、云端合并、编辑态切换、删除场景下无重复描边,线条层级与命中结果不变。
- 检查最终产物中
@b2c-f/drawlinebasic仅存在一份(overrides 生效)。