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

4.7 KiB
Raw Blame History

交易 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 锁优化 SOfutures-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 时阻塞在 getReuseSpiApiByModehasLoggingInRequest 等 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 函数/调用链 故障出现次数 调用次数 总耗时
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