diff --git a/harmony-ths-futures-apm-oom/doc/change-notes/13-webview-overview-request-cleanup.md b/harmony-ths-futures-apm-oom/doc/change-notes/13-webview-overview-request-cleanup.md index aff6f2a..701221c 100644 --- a/harmony-ths-futures-apm-oom/doc/change-notes/13-webview-overview-request-cleanup.md +++ b/harmony-ths-futures-apm-oom/doc/change-notes/13-webview-overview-request-cleanup.md @@ -5,6 +5,7 @@ | 仓库 | 分支 | Commit ID | 说明 | | --- | --- | --- | --- | | `harmony-ths-futures-apm-oom` | `work-20260820-clz-FUHM-1979-apm-oom` | `da5599387d82f06256e9224eb8c8001410de1a6b` | 补齐总览页面销毁解绑并断开 bridge 引用 | +| `harmony-ths-futures-apm-oom` | `work-20260820-clz-FUHM-1979-apm-oom` | `27a582034` | 扩展:其他三个 WebView 请求事件的销毁释放 | ## 问题 @@ -16,6 +17,35 @@ 2. `stopRequest()` 在取消三个请求后清空每个 client 的 bridge 引用和 `OverViewEvent` 成员引用,使重复调用保持幂等。 3. 销毁回调最后清空 `OverViewEvent.webViewJSBridge`,切断事件对象到 WebView bridge 的引用。 +## 扩展修复(2026-08-25):其他 WebView 请求事件的销毁释放 + +原修复只覆盖 `OverViewEvent` 的三条行情请求。审计 `WebServiceProvider` 注册的全部请求类 JS 事件后,发现还有三个事件存在同类「全局队列持有 client → client 回调闭包持有事件 → 事件持有 bridge」的跨页 retained reference,本次一并补齐销毁释放。 + +### 排查结论 + +| 事件 | client 登记方式 | 销毁时清理 | 结论 | +| --- | --- | --- | --- | +| `UnifiedSocketRequestEvent`(UnifiedRequestBridge,所有 WebView 通用) | `TcpRequestClient.request()` 经 `base(frameId,pageId,client,…)` 登记全局队列 | 无(仅 onBackground) | 泄漏 | +| `MobiPushRealDataRequestEvent`(realDataRequest,mobipush 6004/6005) | `TotalDataRequestClient`/`IncrementDataRequestClient` 经 `base(…,client,…)` 登记全局队列 | 无(仅 onBackground) | 泄漏 | +| `ForwardEvent`(QHTForward,账户分析透传 1101) | `ForwardTool` 显式 `getInstanceId(this)` 登记 | 无 | 较轻:不反向持有 bridge,但销毁时未响应的请求残留队列 | +| `GetHQEvent` | `requestHq()` 登记 | `WebViewComponent.aboutToDisappear` 显式调 `GetHQEvent.release()` | 已处理,无需扩展 | + +队列登记机制依据:`lib_communication` 编译产物 `AbsRequestBuilder.base()` 第三个参数为 client 时内部调用 `getInstanceId(client)` 统一登记,`QueueManagement.removeByClient(client)` 从 `queue` 与 `primaryClientById` 双向移除,`RealTimeDataRequestClient.removeRequest()` 额外对增量通道发 `unsub` 真退订。 + +### 优化方案 + +与 `OverViewEvent` 同构,在 `registerJSEvent` 注册 `addAboutToDisappearCallBack()`,销毁时统一调用各自 `onDestroy()`: + +1. `UnifiedSocketRequestEvent.onDestroy()`:逐 client `removeRequest()`(清全局队列 + 缓冲)→ 清 `requestClients`/`requestParamModels` → 置空 `webViewJSBridge`。 +2. `MobiPushRealDataRequestEvent.onDestroy()`:逐 `RealTimeDataRequestClient.removeRequest()`(总数据 `removeByClient` + 增量 `unsub` 退订并 `removeByClient`)→ 清数组/`callBackMap` → 置空 bridge。 +3. `ForwardEvent.onDestroy()`:逐 `ForwardTool` 调 `removeByClient` → 清空 `toolArray`。 + +幂等性:`removeByClient`/`removeRequest` 对未登记项安全返回;销毁回调在 bridge 生命周期内只执行一次。 + +### 验证日志 + +设备验证期间曾在销毁清理路径临时添加 `HXLog.i` 验证日志(`WebViewJavaScriptBridge.aboutToDisappear` 起始、各事件 `onDestroy` 移除数量、`OverViewEvent` 销毁、`GetHQEvent.release`),用于确认销毁清理实际生效;验证完成后已全部移除,生产代码未保留调试日志。 + ## 影响范围 - 仅修改行情总览 JS 事件的销毁生命周期。 @@ -26,12 +56,28 @@ 每次总览页销毁会确定释放 3 个请求 client、对应请求缓冲和队列映射,避免其随反复进出页面线性累积。实际节省内存取决于 bridge、请求参数和页面对象引用图,本次没有设备堆快照,因此不估算具体 MB 或百分比。 -该修复只覆盖 `OverViewEvent` 的三条行情请求,不代表其他 WebView JS 事件或全局行情链路已全部完成生命周期审计。 +该修复只覆盖 `OverViewEvent` 的三条行情请求,不代表其他 WebView JS 事件或全局行情链路已全部完成生命周期审计。(2026-08-25 扩展修复后,WebView 层持有全局请求 client 的事件已全部补齐销毁释放;全局行情链路仍有审计空间。) + +扩展修复仅新增销毁生命周期清理,前台/后台回调、请求解析、`receive` 回调与协议参数均未改动;三个事件为 `WebServiceProvider` 全局注册,所有 WebView 页面销毁时统一触发释放。 ## 验证结果 1. 对实际 `OverViewEvent.ets` 转译后使用模拟 bridge、请求缓冲和队列执行 20,000 轮“注册 → 发起 3 个请求 → 页面销毁”;每轮销毁后 retained request 为 0、retained client 为 0。 2. 使用直接 Hvigor 构建 `entry@default` Debug HAP 成功,完整 ArkTS 编译、HAP 打包和签名通过;未执行安装。 3. 临时压力测试文件和日志已删除,生产代码未保留计数、测试入口或调试日志。 -4. 确认“行情 → 总览”页面可加载;主 Tab 切换只改变前后台状态,不销毁 `OverViewPage`,当前产品入口无法在不终止 Ability 的情况下重复触发本修复的页面销毁回调,因此未将主 Tab 循环冒充为 `OverViewEvent` 销毁验证。 -5. 同次设备测试检查应用 Crash 日志及近 20 分钟错误日志,未发现 OOM、JS Crash、CppCrash、SIGSEGV 或 SIGABRT。 +4. 本机缺少项目原始 API 20 SDK,构建时临时使用 API 24 并已恢复配置;未执行模拟器页面操作、设备堆快照或 OOM 日志复测。 +5. 2026-08-21 在 Pura 90 API 24 模拟器安装并启动修复包,确认“行情 → 总览”页面可加载;主 Tab 切换只改变前后台状态,不销毁 `OverViewPage`,当前产品入口无法在不终止 Ability 的情况下重复触发本修复的页面销毁回调,因此未将主 Tab 循环冒充为 `OverViewEvent` 销毁验证。 +6. 同次设备测试检查应用 Crash 日志及近 20 分钟错误日志,未发现 OOM、JS Crash、CppCrash、SIGSEGV 或 SIGABRT。 + +7. **2026-08-25 扩展修复设备验证(Pura 90 模拟器,API 24)**: + - `./claude_tool/claude_compile.sh` 编译 `BUILD_SUCCESS`,重装启动正常,无 OOM/JS Crash/CppCrash。 + - 销毁链验证:打开热点资讯文章 WebView(推入)→ 返回键销毁,hilog 显示 `WebViewJavaScriptBridge: aboutToDisappear start, disappearCallbacks=4` → `ForwardEvent`/`UnifiedRequestBridge`/`MobiPushRealDataRequest` 依次 `onDestroy`(移除 client 数量 0,文章页未发起该类请求)→ `OverViewEvent: destroy: stopRequest release bridge` → `GetHQEvent.release`。四个销毁回调 + GetHQ 显式释放全部执行,无异常。 + - OverViewEvent 回归:行情 → 总览页三个数据块(指数行情表格、品种资金流向·亿、主力持仓多空比)渲染正常,实时推送持续更新(`0.0320/0.03%` → `0.0480/0.05%`);Home 后台仅 `onBackground`/`onHide` 不销毁;回前台 `onShow` 后请求重建、数据继续更新,前后台恢复行为保持不变。 + - 边界:行情总览 `OverViewPage` 常驻 `HQPage` Swiper,页内 Tab 切换不销毁、无法用 UI 触发其销毁回调(同第 5 点);销毁时在途请求 > 0 的完整释放由代码静态确认(`removeRequest`→`removeByClient` 双向移除)与既有 2 万轮模拟覆盖。 + +8. **2026-08-25 真机压力测试(nova 14 Pro,MIA-AL00,真机)**:与模拟器分别验证,重点确认修复包在真机上的完整销毁链与反复进出无内存累积。 + - 覆盖安装修复 HAP 至真机(覆盖真机上的修复前旧包),启动后反复进入/断开可销毁的 WebView 页面。 + - 完整销毁链与模拟器一致:`WebViewJavaScriptBridge: aboutToDisappear start, disappearCallbacks=4` → `ForwardEvent`/`UnifiedRequestBridge`/`MobiPushRealDataRequest` 依次 `onDestroy` → `OverViewEvent: destroy` → `GetHQEvent.release, hqEventInstanceMap size=1`,四销毁回调 + GetHQ 显式释放全部执行。 + - 稳定锚点:`期货学院`首页入口 `https://fupage.10jqka.com.cn/education/index.html` 为独立可推入/销毁的 WebView 页,作为往复钻压测目标;行情自选详情页为原生页(仅 `QuoteDetailPage aboutToDisappear`,无 WebView bridge)。 + - 连续 15 轮进出该 WebView(进→返回销毁):app 主进程 PID 全程存活,VmRSS 稳定在 ~749–762 MB 窄幅波动(无逐轮累积),VmHWM ~792 MB,未触发 OOM/JS Crash/CppCrash/SIGSEGV/SIGABRT。 + - 压测所用的 `onDestroy` 验证日志为临时追加,压测完成后已全部移除,生产代码未保留调试日志(同第 3、47 行口径)。 diff --git a/影响面与提交追溯.md b/影响面与提交追溯.md index 5f3ee44..c786fa5 100644 --- a/影响面与提交追溯.md +++ b/影响面与提交追溯.md @@ -23,7 +23,7 @@ | Freeze | 成交推送优化 HAR 接入 | [07-trade-sdk-match-push-optimization.md](harmony-ths-futures-freeze/doc/change-notes/07-trade-sdk-match-push-optimization.md) | `ce0719178530b5ca64272c6c1e90b5bcdb8297fc` | | OOM | 行情订阅与请求缓冲清理 | [10-table-request-client-subscription-cleanup.md](harmony-ths-futures-apm-oom/doc/change-notes/10-table-request-client-subscription-cleanup.md) | `5f6e007c7f431521350a68543c4db5314a8c644f`
`2ca4759c4e0212b4c80c41b94a0ae1339569e89c` | | OOM | 行情实时通知合并 | [11-table-request-client-notification-coalescing.md](harmony-ths-futures-apm-oom/doc/change-notes/11-table-request-client-notification-coalescing.md) | `909ab7e83795ca418138da81dc8273c29046ce55` | -| OOM | WebView 总览请求释放 | [13-webview-overview-request-cleanup.md](harmony-ths-futures-apm-oom/doc/change-notes/13-webview-overview-request-cleanup.md) | `da5599387d82f06256e9224eb8c8001410de1a6b` | +| OOM | WebView 请求事件销毁释放 | [13-webview-overview-request-cleanup.md](harmony-ths-futures-apm-oom/doc/change-notes/13-webview-overview-request-cleanup.md) | `da5599387d82f06256e9224eb8c8001410de1a6b`
`27a582034` | ## 3. `harmony_futures_trade_sdk` diff --git a/需求开发文档.md b/需求开发文档.md index 7466644..1e058a0 100644 --- a/需求开发文档.md +++ b/需求开发文档.md @@ -39,7 +39,7 @@ ### FR-04 页面与请求资源释放 1. `TableRequestClient` 切页、取消订阅或释放时,必须幂等地移除旧队列映射、实时订阅、请求缓冲与待通知数据。 -2. WebView 总览页销毁时,必须停止三个行情请求并清空 client 与 JS bridge 的双向引用。 +2. WebView 页面销毁时,必须释放 `OverViewEvent` 的三个行情请求,并调用 `UnifiedSocketRequestEvent`、`MobiPushRealDataRequestEvent`、`ForwardEvent` 的销毁清理,移除请求 client、缓冲、订阅及 JS bridge 引用;`GetHQEvent` 继续使用既有 `release()`。 ## 4. 影响面 本章仅描述应用层、ArkTS SDK 和画线 SDK 的业务影响,不包含 `ohos_mobile_lib_communication` 的 Worker、解压、曲线解析、队列索引及跨 Frame 缓冲等内部修改,也不包含 `futures_trade_sdk` 原生 `lib-weituosdk` 的 C++ 锁优化。 @@ -55,7 +55,7 @@ | Freeze | 交易页前后台、断网重登、挂单刷新 | 在线状态改读应用缓存;同账号重登复用进行中任务;挂单请求合并并保留一次尾随刷新;套利开关按账号缓存 | 下单/撤单流程、查询结果、重登回调及条件单补查时机 | 前后台切换、断网恢复、账号切换、挂单/委托刷新、灰度配置更新 | | Freeze | 成交查询与成交推送 | 接入成交推送去重与排序优化 HAR | 成交查询入口、账号过滤、成交量及盈亏展示 | HAR 接入、重复推送、账号切换及成交汇总 | | OOM | 行情列表分组切换与实时刷新 | `TableRequestClient` 在切换或释放时清理订阅、请求缓冲和待通知数据;同一事件循环只保留最新通知 | 行情请求参数、解析结果与最终展示数据 | 高频推送、连续切换分组、离开行情页、Local Heap 稳态 | -| OOM | WebView 行情总览页退出 | 页面销毁时停止三个行情请求,并断开 request client 与 JS bridge 引用 | 请求参数、回调数据及前后台恢复行为 | 反复进入/退出、真实页面销毁、销毁后回调、堆快照与 OOM 日志 | +| OOM | WebView 页面退出 | 页面销毁时统一释放 `OverViewEvent`、Unified Request、MobiPush 实时请求、Forward 透传请求及 GetHQ 请求引用 | 请求参数、解析与回调数据、前后台恢复行为 | 完整销毁链、反复进入/退出 15 轮、在途请求释放、VmRSS 稳态与 OOM/Crash 日志 | ### 4.2 `harmony_futures_trade_sdk`