4.4 KiB
交易 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 | 函数/调用链 | 故障出现次数 | 调用次数 | 总耗时 |
|---|---|---|---|---|
| 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() 风险,需新包线上复采确认。
优化方案
- 删除
FuturesApiInterceptor中无实际拦截效果的请求前检查。原逻辑会在每次交易请求前同步查询登录中、在线状态,但两个判断分支中的拦截代码均已注释。删除后不改变当前请求行为,同时避免业务请求重复进入 Native 锁域。 TradeApiManager按交易账号复用正在执行的重登 Promise。同一账号由认证、交易页或推送重复触发重登时,只执行一次 SDK 登录,其余调用复用结果并保留各自成功、失败回调。- 在线检查和复用连接查询前先判断该账号是否正在重登,避免登录过程中再次同步查询 Native 状态。
影响范围
- 交易接口发送、自动重登、推送触发的在线检查和交易页切换重登。
- 不修改交易 SDK、Native SO、登录参数、失败重试次数及成功/失败业务处理。
- 不将 SDK 对象迁移到 Worker 或 TaskPool,不改变其线程归属。
预期收益与边界
优化可减少主线程进入交易 SDK 互斥锁的频率,并阻止同账号重复登录放大锁竞争。tryToReLoginAccount 首次判断仍需调用一次 getReuseIpForLogin,因此这属于应用侧止血;彻底消除锁等待仍需要 SDK 缩小 Native 锁范围并发布新的 SO。
验证建议
在持续发送交易请求时反复执行断网重连、前后台切换、推送唤起和交易账号切换,确认同账号并发登录数不超过 1,并检查冻屏主线程栈中是否仍出现 mutex::lock → getReuseSpiApiByMode/hasLoggingInRequest。