Files

34 lines
2.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 画线绘制候选集去重 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 → isSameLine``drawLines()` 每帧渲染都会调用 `getLinesToDraw()` 重建绘制候选集,其中 `appendUniqueLines``source.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` 随之删除。
## 影响范围
- 仅画线绘制候选集的去重实现;画线数据模型、持久化、云端合并、绘制样式与命中逻辑不变。
- 每帧绘制候选集重建仍会分配三个 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 生效)。