帮你解锁 Android 性能优化五大误区和两大疑点!(1),2024年最新华为HarmonyOS鸿蒙面试
各个版本之间的垃圾收集性能都有显著的改善,如今,垃圾收集对应用程序的流畅已经几乎没有影响了。下图展示了 Google 官方在 Android 10 中对具有分代并发收集的对象收集所做的改进,新版本的 Android 11 中也有明显的改进。

在 GC 基准测试(例如 H2)中,吞吐量大幅提高了 170% 以上,而在实际应用(如 Google Sheets)中,吞吐量也提高了 68%。
如果认为垃圾收集效率低下并且内存分配负担很重,那么就相当于认为创建的垃圾越少,垃圾收集工作就越少,因此,代替每次使用时都创建新对象,我们可以维护一个经常使用的类型的对象池,然后从池中获取已创建的对象,如下:
Pool pool[] = new Pool<>[50];
void foo() {
A a = pool.acquire();
…
pool.release(a);
}
这里省略了代码细节,大体就是就是定义了一个 pool,从 pool 中获取对象,然后最终释放。
要测试这种场景,我们使用微基准测试 (microbenchmark):从池中测试分配对象的开销,以及 CPU 的开销,来确定垃圾回收是否会影响应用程序的性能。
在这种情况下,我们依然可以在装有 Android 10 的 Pixel 2 XL 上循环运行了数千次分配对象的代码,因为对于小型或大型对象,性能可能会有所不同,我们还通过添加不同的字段来模拟不同的对象大小,最终的开销结果如下:

用于垃圾回收的 CPU 开销的结果如下:

从图中可以看出,标准分配和池化对象之间的差异也很小,但是,当涉及到较大对象的垃圾回收时,池解决方案略微高一点。
这个结果并不意外,因为池化对象会增加应用的内存占用量,此时,应用突然占用了太多的内存,即使由于池化对象减少了垃圾回收调用的数量,每个垃圾回收调用的成本也更高,因为垃圾收集器必须遍历更多的内存才能确定哪些对象需要被收集,哪些对象需要保留。
那么,对象是否应该被池化,这还是主要取决于应用的需求。如果不考虑到代码复杂性,池化对象有如下缺点:
- 提高内存占用量
- 使对象存活变长
- 需要非常完善的对象池机制
但是,池的方法对于大并且耗时的对象分配可能确实是有效的,关键是要记住在选择方案之前进行充分的测试。
误区五:debug 模式下进行性能分析
在 debug 的同时对应用进行性能分析非常方便,毕竟,我们通常也是在 debug 模式下进行编码的,并且,即使 debug 应用中的性能分析不准确,也可以更快地进行迭代修改提高效率,然后事实是并没有。
为了验证这一误解,我们分析了 Activity 相关的常见操作过程过的测试结果,如下图:

在某些测试(例如反序列化)中,debug 与否对性能没有影响,但是,有些结果却有 50% 甚至以上的差别,我们甚至发现结果速度可能会慢 100% 的例子,这是因为 runtime 在 debug 模式下时对代码几乎没有优化,因此与用户在生产设备上运行的代码有很大不同。
在 debug 模式下进行性能分析的结果是可能会误导优化方向,导致浪费时间来优化不需要优化的内容。
疑点
现在,我们需要有意识的逃避上述提到的五大误区,下面我们再来看一下一些日常开发中不太明显,但我们经常会有的疑惑的问题,事实结果可能也与我们想的大相径庭。
疑点 1:Multidex:是否影响应用性能?
如今的 APK 文件越来越大,因为大型应用通常会超出 Android 限定的方法数量,从而使用 Multidex 方案打破传统的 dex 规范。
问题是,多少方法可以称之为多?而且如果应用包含大量 dex 是否对性能产生影响?很多时候我们也并不是因为应用太大,而是为了根据功能拆分 dex 文件来方便团队开发而使用 Multidex。
为了测试多个 dex 文件对性能的影响,我们使用了计算器应用,默认情况下,它只包含单个 dex 文件,我们可以根据其程序包边界将其拆分为五个 dex 文件,来根据功能部件模拟拆分。
首先,测试启动应用的性能,结果如下:

因此,拆分 dex 文件对此处并没有影响,对于其他应用,可能会因为某些因素而产生轻微的开销:应用程序的大小以及拆分方式。但是,只要合理地分割 dex 文件并且不添加成百个 dex 文件,对启动时间的影响应该不大。
接下来是 APK 的大小和内存消耗:


如图所示,APK 大小和应用的运行时内存占用量都略有增加,这是因为将应用程序拆分为多个 dex 文件时,每个 dex 文件都会有一些符号表和缓存表中的重复数据。
但是,我们可以通过减少 dex 文件之间的依赖关系来最大限度地避免这种情况,在这个案例中,并没有将 dex 包量化,我们可以使用 R8 和 D8 之类的工具合理分析项目结构并使用最小化的依赖关系,这些工具可以自动拆分 dex 文件,并帮助我们避免常见的错误,最大程度地减少依赖关系,如创建的 dex 文件数量不会超过指定的数量,并且不会将所有启动类都放置在主文件中。但是,如果我们对 dex 文件进行自定义拆分,请确保合理分析。
疑点 2:无用代码
使用 ART 这样的即时编译器的好处之一就是可以在运行时分析代码,并对其进行优化。有一种说法是,如果解释器 / JIT 系统没有对代码进行概要分析,就可能不会执行该代码。为了验证这一理论,我们检查了 Google 应用生成的 ART 配置文件,发现许多代码并没有被 JIT 做概要分析,这就表明许多代码实际上从未在设备上执行过。
有几种类型的代码可能无法剖析:
- 错误处理代码,希望它不会执行太多。
- 兼容性代码,并非在所有设备上都执行的代码,尤其是 Android 5 以上版本的设备。
- 不常用功能的代码。
但是,从结果分布来看,应用程序中还是会存在很多不必要的代码。R8 可以帮助我们快速,简便,免费地删除不必要的代码,来缩小这部分的开销。如果不这么做,我们也可以将应用打包成 Android App Bundle,这种格式只会使用特定设备所需的代码和资源来运行应用。
总结
本文,我们分析了 Android 性能优化的五个误区,但某些情况下数据的结果还并不清晰,我们需要做的就是在优化和修改代码之前尽量做好性能测试。
目前,已经有很多工具可以帮助我们分析评估如何优化应用了,如 Android Studio 中的 profilers,它也提供了电池和网络的监测功能。也可以用一些工具做更深入的探究,如 Perfetto 和 Systrace,这些工具会提供更加详细的功能,例如在应用启动或执行过程中发生的具体情况。
Jetpack Benchmark 摒弃了监测和基准测试的所有复杂操作,官方强烈建议我们在持续集成系统中使用它来跟踪性能,并查看应用在添加功能的行为,最后需要注意的一点是,不要在 debug 模式下分析应用性能。
为了帮助到大家更好的全面清晰的掌握好性能优化,准备了相关的学习路线以及核心笔记(还该底层逻辑):https://qr18.cn/FVlo89 大家可以进行参考学习:
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数HarmonyOS鸿蒙开发工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年HarmonyOS鸿蒙开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。



既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上HarmonyOS鸿蒙开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新
如果你觉得这些内容对你有帮助,可以添加VX:vip204888 (备注鸿蒙获取)

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
ip204888 (备注鸿蒙获取)**
[外链图片转存中…(img-mLvqnRUz-1712766322880)]
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
更多推荐

所有评论(0)