58 lines
4.7 KiB
Markdown
58 lines
4.7 KiB
Markdown
# 交易 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 耗时函数线上统计中:
|
||
|
||
| 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 | 函数/调用链 | 故障出现次数 | 调用次数 | 总耗时 |
|
||
| ---: | --- | ---: | ---: | ---: |
|
||
| 1–4 | `getReuseIpForLogin → getRequestIpForLogin → libweituo_sdk_ohos.so` | 75 | 750 | 900000ms(分层重复采样) |
|
||
| 5–6 | `FuturesApiInterceptor.interceptSendMsg*` | 67/64 | 670/640 | 201000/192000ms |
|
||
| 11–18 | `enqueue → awaitEnqueue → innerEnqueue → startSendRequest → proceedSendMsg` | 47–48 | 470–480 | 141000–144000ms/项(分层重复采样) |
|
||
| 19–20 | `TradeApiManager.tryToReLoginAccount` 及其匿名闭包 | 44 | 440 | 132000ms/项 |
|
||
|
||
TOP1–4 和 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`。
|