Android tinker升级之路分析

前言

目前app线上的tinker版本为 1.9.14.19,在最近的几个版本技术需求中,我们希望对tinker尝试进行升级,并对内部封装的tinker的包装sdk进行升级。升级过程中的一些热修流程和记录如下。

热修耗时时长分析

测试中,所有测试热修基本均可生效,但是对补丁合成生效时间有要求。耗时具体体现在:

  • tinker初始化
  • 下载补丁包
  • recover dex耗时(合并新dex文件)
  • parallel optimize dex(oat耗时)
  • 保存补丁信息(更新patch.info文件)

测试结果发现除了parallel optimize dex这一步,其他步骤耗时对比几乎不变,且耗时时长集中在parallel optimize dex这一环节。

升级前后数据对比

start to parallel optimize dex的时间对比(oat耗时)

机型耗时(ms) 线上包(版本:1.9.14.19)耗时(ms) 升级包(版本:1.9.14.25.2)
pixel 6a(Android 13)6333393393
180293400
185893386
vivo x80(Android 13)6336093399
284993457
小米10(android 12)6337593435
6333893368
华为mate40(android 12)448737506
500734520
小米8(Android 9)62056439
61486220
vivo x9plus(Android 7.1.2)78312 (热修不生效)78035 (热修不生效)
131601 (热修不生效)79475 (热修不生效)
小米5s Plus(Android 6.0.1)7661387717
6461762501

不同Android系统下tinker的oat流程总结

  • 华为荣耀系统tinker会通过registerDexModule方法注册dex,不会进行重试步骤(1.9.14.25.2版本重试10次,1.9.14.19版本重试3次);
  • android8.0 之下直接使用DexFile.loadDex加载补丁触发dex2oat;
  • android8 ~ android10,通过NewClassLoaderInjector.triggerDex2Oat进行dex2oat;
  • android10以后不再支持从应用进程调用dex2oat,仅接受系统生成的OAT文件(TinkerDexOptimizer.triggerPMDexOptOnDemand方法);
  • 重试的逻辑发生在TinkerDexOptimizer.triggerPMDexOptOnDemand方法中,DexFile.loadDex和进程内通过NewClassLoaderInjector.triggerDex2Oat进行dex2oat不会走该逻辑;该重试的逻辑会增加30s耗时。
  • 在老旧手机上步骤二recover dex耗时明显比新设备耗时长,这个和机型性能有关,升级的差异不在步骤二。

相关逻辑请参考版本tinker源码TinkerDexOptimizer.OptimizeWorker类的run方法。

附:patch合成生效时间分析

目前热修是肯定需要重启app的,但是在app拉取热修配置,下载patch包,然后重启app之前的这个时间节点上,tinker需要对patch包进行合成生效的操作,这部分会有耗时。

tinker核心代码:

TinkerPatchService 
         -  doApplyPatch(this, intent);

tinker issue上已经有人反馈了:

补丁从安装到提示安装成功需要多久,我就改了个Toast打印的字符串,需要大概100s,这正常吗?项目比较大 · Issue #1316 · Tencent/tinker · GitHub

最新版本补丁合成很慢(50s),不管 dex2oat 是否成功都会循环 N 次 · Issue #1670 · Tencent/tinker · GitHub

这个问题tinker *v1.9.14.25* 已经做了优化:

**1、**base包更新或有新 patch 合成成功后删除老 patch 的逻辑改为异步实现以降低启动耗时。

**2、**dexopt 触发重试次数缩减到 10 次,避免部分机型 apply patch 耗时太长。

但是从tinker目前的反馈来看,最新的几个版本会出现合成时间变长的case,目前还处于open状态。为了验证升级之后的tinker,在合成生效时间上与之前版本的差异,进行了线上tinker版本(1.9.14.19)的对照测试。测试见下。

image-20230914100146884

附:tinker版本升级内容记录

*v1.9.14.20*

  1. 修复了 OPPO & VIVO 部分机型加载 Tinker 时偶现的闪退问题。
  2. 增加了 Patch Dex 的 Dex2Oat 重试次数,以降低解释模式加载 Patch Dex 的概率。

*v1.9.14.21*

  1. 尝试修复极少数情况下因为 resources.apk 被意外修改导致 patch 后的资源找不到或失效的问题。

*v1.9.14.22*

  1. 修复了偶现的 Tinker ID 注入失败导致 Patch 包编译失败的问题。

*v1.9.14.23*

  1. 优化了判断 resources.apk 被意外修改导致资源 patch 失效的检测逻辑。
  2. 修复了连续两次 patch 中间更新了 base 包时可能导致最后一次 patch 失效的问题。
  3. 在 Patch 加载不成功时 installNativeLibraryABIWithoutTinkerInstalled() 方法不再注入 patch so 路径,避免 dex 和 so 不一致的问题。

*v1.9.14.23.1*

  1. 修复了 Android 4.4 设备上 getCurrentInstructionSet() 失败的问题

*v1.9.14.24*

  1. 修复了 R8 生成的特殊 DebugInfo 导致编译失败的问题。
  2. 增加 performSecondaryDexOpt 的重试次数,在重试失败后再尝试 registerDexModule,以尽量减小 Android R 上 odex 没有生成导致的性能开销。
  3. 在 performSecondaryDexOpt 重试无效前不在 OPPO、VIVO、XIAOMI、REDMI 的 Android S 或更新的系统上调 registerDexModule,规避已知的性能问题。
  4. 更新 *getProcessName* 的实现,在 *Android P* 及更新的系统上优先尝试 *Application.getProcessName()* 方法。

*v1.9.14.25*

  1. 增加了32位 Android N 及更旧的系统上使用解释模式触发 dexopt 的开关以帮助减少 32位上 VmSize 的开销。
  2. 修复部分机型上资源有变更时 patch 失败的问题。
  3. base包更新或有新 patch 合成成功后删除老 patch 的逻辑改为异步实现以降低启动耗时。
  4. dexopt 触发重试次数缩减到 10 次,避免部分机型 apply patch 耗时太长。

*v1.9.14.25.1*

  1. 修复了 anim 资源新增、修改检测逻辑,在 anim 资源发生新增或修改时会中断编译。
  2. 获取当前进程名的方法在 api level >= 18 的机器上优先使用反射 ActivityThread 的方式实现,若失败则改用 BufferedReader 读 proc 的方式实现。

*v1.9.14.25.2*

  1. 修复了部分机型上无法加载新增资源及修改资源不生效的问题(flutter加载asset时必现)。
  2. 新增了异步触发patched dex的dex2oat并且不等待其执行完毕的patch合成接口,以满足开启时长较短的App紧急修复问题时需要Patch能快速生效的需求。

参考

Android 热修复Tinker源码分析(二)补丁包的合成 - 掘金

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

许进进

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值