性能优化及工具 | 青训营笔记

146 阅读8分钟

这是我参与「第四届青训营 」笔记创作活动的第8天

为什么要做性能优化

  • 了解性能优化与业务发展之间的关系

    • Android发展至今,各项基础设施非常完善的情况下,我们越来越重视App的性能优化,以及用户体验,这关乎一个线上应用的业务数据持续增长的基础,以及用户口碑的问题
  • PC平台和移动平台的硬件性能优化的发展历程

    • 通过x86平台和arm平台的发展历史,来展望性能优化
  • 在长时间的历史范围内看整体的优化趋势和软件优化能带来的优势

    • 硬件与软件的结合也是最佳的体验的基础
  • 用实际的例子介绍性能优化的必要性

    • Talk is cheap

性能优化是什么

性能优化的主要目标

  • :最快显示效率、最快网络速率、最快UI响应
  • :最佳用户体验,减少强打断
  • :最低存储、最低功耗、最低流量消耗、最低计算资源

流畅性优化

Google 定义:界面呈现是指从应用生成帧并将其显示在屏幕上的动作。要确保用户能够流畅地与应用互动,应用呈现每帧的时间不应超过 16ms,以达到每秒 60 帧的呈现速度,

资源优化

  • 最大化资源调度:最大资源调度分为两个方向,第一个方向将一些有限资源尽量向最影响体验的方向靠拢,首先要满足,我们需要在网络、渲染等领域提供更多的资源。第二个方向,探寻更多的资源供给,首先要满足,深度剖析系统资源使用,需要从系统层榨取更多的可用资源,也需要从用户敏感角度榨取更多资源,最终实现最大化资源调度。
  • 最小化资源使用:需要对持续性的指标影响降到最低,首先要满足,我们对功耗、存储、流量等指标在一些用户敏感度大于实际获得的体验的环境下,保障核心功能的体验。本质的原则就是保证业务基本面的前提下,通过降级或者优化等手段,将占用的资源做到最小。

稳定性优化

当性能劣化累积到一定程度,就变成了稳定性问题,直接强制打断应用的使用体验。

系统级优化

如何充分利用应用程序和系统程序,综合提升应用的性能表现。有哪些可以挖掘的点。

最佳工具选型

性能监控工具的价值

App的性能问题包括崩溃、网络请求错误或超时、响应速度慢、列表滚动卡顿、流量大、耗电等等。而导致App性能低下的原因有很多,除去设备硬件和软件的外部因素,其中大部分是开发者错误地使用线程、锁、系统函数、编程范式、数据结构等导致的。即便是最有经验的程序员,也很难在开发时就能避免所有导致性能低下的“坑”,因此解决性能问题的关键是在于能不能尽早地发现和定位这些“坑”。

Gpu呈现模式

放大的 GPU 渲染模式分析图形。

下表介绍了使用运行 Android 6.0 及更高版本的设备时分析器输出中某个竖条的每个区段。

Layertool

抖音自研工具,快速识别图层及过度绘制、绘制区域过大等问题,提升整体渲染效率.

CPU Profiler

如需打开 CPU 性能剖析器,请按以下步骤操作:

  1. 依次选择 View > Tool Windows > Profiler 或点击工具栏中的 Profile 图标
  1. 如果 Select Deployment Target 对话框显示提示,请选择需将您的应用部署到哪个设备上以进行性能剖析。如果您已通过 USB 连接设备但系统未列出该设备,请确保您已启用 USB 调试
  1. 点击 CPU 时间轴上的任意位置以打开 CPU 性能剖析器。
  • 当您打开 CPU 性能分析器时,它会立即开始显示应用的 CPU 使用率和线程活动。系统会显示类似于图 1的界面。

CPU 性能分析器的默认视图包括以下时间轴:

  1. 事件时间轴:显示应用中的 activity 在其生命周期内不断转换经历各种不同状态的过程,并指示用户与设备的交互,包括屏幕旋转事件。如需了解如何在搭载 Android 7.1(API 级别 25)及更低版本的设备上启用事件时间轴,请参阅启用高级性能分析功能
  1. CPU 时间轴:显示应用的实时 CPU 使用率(以占总可用 CPU 时间的百分比表示)以及应用当前使用的线程总数。此时间轴还会显示其他进程(如系统进程或其他应用)的 CPU 使用率,以便您可以将其与您应用的 CPU 使用率进行对比。您可以通过沿时间轴的横轴方向移动鼠标来检查历史 CPU 使用率数据。
  1. 线程活动时间轴:列出属于应用进程的每个线程,并使用下面列出的颜色在时间轴上指示它们的活动。记录轨迹后,您可以从此时间轴上选择一个线程,以在轨迹窗格中检查其数据。

    1. 绿色:表示线程处于活动状态或准备使用 CPU。也就是说,线程处于正在运行或可运行状态。
    2. 黄色:表示线程处于活动状态,但它正在等待一项 I/O 操作(如磁盘或网络 I/O),然后才能完成它的工作。
    3. 灰色:表示线程正在休眠且没有消耗任何 CPU 时间。 当线程需要访问尚不可用的资源时,就会出现这种情况。在这种情况下,要么线程主动进入休眠状态,要么内核将线程置于休眠状态,直到所需的资源可用。
  1. CPU 性能分析器还会报告 Android Studio 和 Android 平台添加到应用进程的线程的 CPU 使用率,这些线程包括 JDWPProfile SaverStudio:VMStatsStudio:PerfaStudio:Heartbeat 等(不过,它们在线程活动时间轴上显示的确切名称可能有所不同)。Android Studio 报告此数据是为了方便您确定线程活动和 CPU 使用率什么时候是由应用的代码实际引发的。

耗时拆解

  1. CPU Time 指占用CPU进行计算所花费的时间绝对值,中断、挂起、休眠等行为是不会增加CPU Time的,所以因CPU Time开销占比高导致的不合理耗时点往往是逻辑本身复杂冗长需要消耗较多cpu时间片才能处理完。比较常见的高CPU占用是循环,比如抖音启动时遇到过一个so加载耗时,最后定位原因是在解压so的时候,遍历ZipEntry的次数过多导致,一个可行的优化策略就是可以把so所在的ZipEntry提前,遍历完so的ZipEntry之后可以提前中止遍历,而不需要遍历剩下的无效ZipEntry。
  1. CPU Schedule 在分析时主要针对主线程,是指主线程处于可执行状态但获取不到cpu时间片,这类耗时可能和线程调度等有关,最终导致分配给主线程的cpu时间片不足以及时处理完其内任务。由于主线程的线程优先级比其他线程的优先级要高很多,通常影响并不大,事实上抖音做了线上用户的启动耗时统计,这部分的耗时占比也是不大的。不过有一个场景需要关注,就是渲染,渲染是需要RenderThread提交GPU的渲染命令,而RenderThread并没有主线程那么高的优先级,因此比较容易受CPU的负载的影响,导致渲染耗时。
  1. IO Wait 指发生了IO操作需要等待IO返回结果,这类耗时可能发生在读取资源和文件,类加载,甚至在内存不足时的PageFault都会导致IO Wait。
  1. Lock Wait 也是主要针对主线程,指其处于等锁状态,等待被其他线程唤醒或自己超时唤醒,导致这类耗时的问题种类多样,大体也是可以分为业务锁和系统锁,业务锁主要是被主线程等待的业务逻辑未能及时处理完,优化思路一般是移除主线程的锁等待逻辑或者加快被等待的业务逻辑的执行速度。系统锁主要有:String InternTable Lock,ClassLinker Lock,GC Wait Lock等
  1. IPC 指进程间通信,操作系统大都含有相应的机制,Android中所特有的IPC机制是Binder,由于进行IPC调用往往需要等待通信结果本质上这也算是一种Lock Wait,但Android特有Binder机制所以单独列出,这类耗时可采用减少或替代Binder调用等手段来优化

参考资料

【Android 客户端专场 学习资料三】第四届字节跳动青训营