Files
future-harmony-freeze-oom-fix/harmony-ths-futures-freeze/doc/change-notes/05-trade-sdk-native-lock-app-mitigation.md
T

58 lines
4.4 KiB
Markdown
Raw 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.
# 交易 SDK Native 锁竞争应用侧优化
## 修复提交
| 仓库 | 分支 | Commit ID | 说明 |
| --- | --- | --- | --- |
| `harmony-ths-futures` | `work-20260818-clz-FUHM-1979-apm-appfreeze` | `d04f7720c13b130bd9bdab69109d6a93c6edcfca` | 应用侧减少交易 SDK Native 锁竞争(`FuturesApiInterceptor`/`TradeApiManager` |
| `futures_trade_sdk`(原生 lib-weituosdk | `work-clz-FUHM-1979-native-lock-opt` | `1ba241ef8d9aae16dde1b0c4e406d6cd41cca216` | 链接复用计数由 `recursive_mutex` 改为 `std::atomic`,降低锁竞争 |
Native 锁优化 SO`futures-trade-sdk-so-1.2.0-lock-opt.har`)由上述 SDK 提交构建(lib-weituosdk 的 `futures_spi_api_manager.cpp`/`futures_quants_spi.cpp`/`.h`)。应用侧止血见上表首行;本工程 `oh-package.json5` 指向该 SO 的接入改动尚未提交。
## 问题
冻屏日志显示,主线程调用交易 SDK 时阻塞在 `getReuseSpiApiByMode``hasLoggingInRequest` 等 Native 锁上。高频入口包括交易请求发送前检查和自动重登检查。
## 线上真实数据补充
2026-08-21 补充的 TOP10 耗时函数线上统计中,交易 SDK 发送链路仍被采样命中:
| TOP | 函数 | 故障出现次数 | 调用次数 | 总耗时 |
| ---: | --- | ---: | ---: | ---: |
| 7 | `sendMsg entry\|@b2c-f/futures_ohos_trade_sdk\|1.0.13\|src/main/ets/trade/api/rpc/RspSendMsgCenterImpl.ts` | 1 | 10 | 3000ms |
| 4 | `isNumber entry\|@b2c-f/futures_ohos_trade_sdk\|1.0.13\|src/main/ets/trade/util/StringUtil.ts` | 1 | 2 | 600ms |
`sendMsg()` 是交易请求进入 SDK/Native 的关键同步入口,和本 notes 记录的 Native 锁竞争止血方向一致。`isNumber()` 为短函数,单独看不像根因,更可能是交易列表或请求参数处理链路中的采样帧;应结合完整调用栈判断是否被 `sendMsg()` 或列表刷新长任务包裹。
同日 TOP20 统计进一步命中交易 SDK 的两组调用链:
| TOP | 函数/调用链 | 故障出现次数 | 调用次数 | 总耗时 |
| ---: | --- | ---: | ---: | ---: |
| 14 | `getReuseIpForLogin → getRequestIpForLogin → libweituo_sdk_ohos.so` | 75 | 750 | 900000ms(分层重复采样) |
| 56 | `FuturesApiInterceptor.interceptSendMsg*` | 67/64 | 670/640 | 201000/192000ms |
| 1118 | `enqueue → awaitEnqueue → innerEnqueue → startSendRequest → proceedSendMsg` | 4748 | 470480 | 141000144000ms/项(分层重复采样) |
| 1920 | `TradeApiManager.tryToReLoginAccount` 及其匿名闭包 | 44 | 440 | 132000ms/项 |
TOP14 和 TOP19–20 共同指向自动重登录入口的同步复用 IP 查询;TOP11–18 是同一请求链的多层采样,不能直接累加为独立损耗。该 TOP20 文件记录的是旧版 `1.0.11/1.1.1`,当前工程已接入 `1.0.13/1.2.0` 锁优化 SO;应用侧仍保留首次同步 `getReuseIpForLogin()` 风险,需新包线上复采确认。
## 优化方案
1. 删除 `FuturesApiInterceptor` 中无实际拦截效果的请求前检查。原逻辑会在每次交易请求前同步查询登录中、在线状态,但两个判断分支中的拦截代码均已注释。删除后不改变当前请求行为,同时避免业务请求重复进入 Native 锁域。
2. `TradeApiManager` 按交易账号复用正在执行的重登 Promise。同一账号由认证、交易页或推送重复触发重登时,只执行一次 SDK 登录,其余调用复用结果并保留各自成功、失败回调。
3. 在线检查和复用连接查询前先判断该账号是否正在重登,避免登录过程中再次同步查询 Native 状态。
## 影响范围
- 交易接口发送、自动重登、推送触发的在线检查和交易页切换重登。
- 不修改交易 SDK、Native SO、登录参数、失败重试次数及成功/失败业务处理。
- 不将 SDK 对象迁移到 Worker 或 TaskPool,不改变其线程归属。
## 预期收益与边界
优化可减少主线程进入交易 SDK 互斥锁的频率,并阻止同账号重复登录放大锁竞争。`tryToReLoginAccount` 首次判断仍需调用一次 `getReuseIpForLogin`,因此这属于应用侧止血;彻底消除锁等待仍需要 SDK 缩小 Native 锁范围并发布新的 SO。
## 验证建议
在持续发送交易请求时反复执行断网重连、前后台切换、推送唤起和交易账号切换,确认同账号并发登录数不超过 1,并检查冻屏主线程栈中是否仍出现 `mutex::lock → getReuseSpiApiByMode/hasLoggingInRequest`