这是我参与「第四届青训营 」笔记创作活动的的第12天
一、前言
*今天学习到的是Android 客户端专场 学习资料三】第四届字节跳动青训营中的Android的第七节:初识性能优化及工具,在 Android开发中,性能优化策略十分重要因为其决定了应用程序的开发质量:可用性、流畅性、稳定性等
二、本节课知识点大纲:
为什么要做性能优化 性能优化是什么? 最佳工具选型
为什么要做性能优化
-
了解性能优化与业务发展之间的关系
-
PC平台和移动平台的硬件性能优化的发展历程
-
在长时间的历史范围内看整体的优化趋势和软件优化能带来的优势
-
用实际的例子介绍性能优化的必要性
性能优化是什么?
- 性能优化的主要目标是什么
-
- 快:最快显示效率、最快网络速率、最快UI响应
- 稳:最佳用户体验,减少强打断
- 省:最低存储、最低功耗、最低流量消耗、最低计算资源
性能监控工具的价值
App的性能问题包括崩溃、网络请求错误或超时、响应速度慢、列表滚动卡顿、流量大、耗电等等。而导致App性能低下的原因有很多,除去设备硬件和软件的外部因素,其中大部分是开发者错误地使用线程、锁、系统函数、编程范式、数据结构等导致的。即便是最有经验的程序员,也很难在开发时就能避免所有导致性能低下的“坑”,因此解决性能问题的关键是在于能不能尽早地发现和定位这些“坑”。
-
Gpu呈现模式
下表介绍了使用运行 Android 6.0 及更高版本的设备时分析器输出中某个竖条的每个区段。
Layertool
抖音自研工具,快速识别图层及过度绘制、绘制区域过大等问题,提升整体渲染效率.
CPU Profiler
如需打开 CPU 性能剖析器,请按以下步骤操作:
- 依次选择 View > Tool Windows > Profiler 或点击工具栏中的 Profile 图标
- 如果 Select Deployment Target 对话框显示提示,请选择需将您的应用部署到哪个设备上以进行性能剖析。如果您已通过 USB 连接设备但系统未列出该设备,请确保启用 USB 调试
- 点击 CPU 时间轴上的任意位置以打开 CPU 性能剖析器。
- 当您打开 CPU 性能分析器时,它会立即开始显示应用的 CPU 使用率和线程活动。系统会显示类似于图 1的界面。
CPU 性能分析器的默认视图包括以下时间轴:
- 事件时间轴:显示应用中的 activity 在其生命周期内不断转换经历各种不同状态的过程,并指示用户与设备的交互,包括屏幕旋转事件
- CPU 时间轴:显示应用的实时 CPU 使用率(以占总可用 CPU 时间的百分比表示)以及应用当前使用的线程总数。此时间轴还会显示其他进程(如系统进程或其他应用)的 CPU 使用率,以便您可以将其与您应用的 CPU 使用率进行对比。您可以通过沿时间轴的横轴方向移动鼠标来检查历史 CPU 使用率数据。
-
线程活动时间轴:列出属于应用进程的每个线程,并使用下面列出的颜色在时间轴上指示它们的活动。记录轨迹后,您可以从此时间轴上选择一个线程,以在轨迹窗格中检查其数据。
- 绿色:表示线程处于活动状态或准备使用 CPU。也就是说,线程处于正在运行或可运行状态。
- 黄色:表示线程处于活动状态,但它正在等待一项 I/O 操作(如磁盘或网络 I/O),然后才能完成它的工作。
- 灰色:表示线程正在休眠且没有消耗任何 CPU 时间。 当线程需要访问尚不可用的资源时,就会出现这种情况。在这种情况下,要么线程主动进入休眠状态,要么内核将线程置于休眠状态,直到所需的资源可用。
- CPU 性能分析器还会报告 Android Studio 和 Android 平台添加到应用进程的线程的 CPU 使用率,这些线程包括
JDWP、Profile Saver、Studio:VMStats、Studio:Perfa和Studio:Heartbeat等(不过,它们在线程活动时间轴上显示的确切名称可能有所不同)。Android Studio 报告此数据是为了方便您确定线程活动和 CPU 使用率什么时候是由应用的代码实际引发的。
TraceView
打开跟踪日志后,Traceview 会使用以下两个窗格显示日志数据:
- 时间轴窗格,说明每个线程何时进入和退出某个方法
- 剖析窗格,总结每个线程在跟踪日志期间的执行情况
时间轴窗格
- 图3显示了时间轴窗格的特写。每个线程的执行情况都显示在各自的行中,并且越往右使用的时间越长。每个方法都以不同的颜色显示。第一行下面的细线显示所选方法的子级(从进入到退出)。
分析窗格
- 对于分析窗格中的每个顶级节点,表中的 Calls + Rec, Calls/Total 列(图 4 中未显示)会报告对相应方法的调用次数和递归调用的次数。而对于父方法和子方法,此列会显示被调用方法为顶级节点中方法的子级或父级的调用次数。
耗时拆解
- CPU Time 指占用CPU进行计算所花费的时间绝对值,中断、挂起、休眠等行为是不会增加CPU Time的,所以因CPU Time开销占比高导致的不合理耗时点往往是逻辑本身复杂冗长需要消耗较多cpu时间片才能处理完。比较常见的高CPU占用是循环,比如抖音启动时遇到过一个so加载耗时,最后定位原因是在解压so的时候,遍历ZipEntry的次数过多导致,一个可行的优化策略就是可以把so所在的ZipEntry提前,遍历完so的ZipEntry之后可以提前中止遍历,而不需要遍历剩下的无效ZipEntry。
- CPU Schedule 在分析时主要针对主线程,是指主线程处于可执行状态但获取不到cpu时间片,这类耗时可能和线程调度等有关,最终导致分配给主线程的cpu时间片不足以及时处理完其内任务。由于主线程的线程优先级比其他线程的优先级要高很多,通常影响并不大,事实上抖音做了线上用户的启动耗时统计,这部分的耗时占比也是不大的。不过有一个场景需要关注,就是渲染,渲染是需要RenderThread提交GPU的渲染命令,而RenderThread并没有主线程那么高的优先级,因此比较容易受CPU的负载的影响,导致渲染耗时。
- IO Wait 指发生了IO操作需要等待IO返回结果,这类耗时可能发生在读取资源和文件,类加载,甚至在内存不足时的PageFault都会导致IO Wait。
- Lock Wait 也是主要针对主线程,指其处于等锁状态,等待被其他线程唤醒或自己超时唤醒,导致这类耗时的问题种类多样,大体也是可以分为业务锁和系统锁,业务锁主要是被主线程等待的业务逻辑未能及时处理完,优化思路一般是移除主线程的锁等待逻辑或者加快被等待的业务逻辑的执行速度。系统锁主要有:String InternTable Lock,ClassLinker Lock,GC Wait Lock等
- IPC 指进程间通信,操作系统大都含有相应的机制,Android中所特有的IPC机制是Binder,由于进行IPC调用往往需要等待通信结果本质上这也算是一种Lock Wait,但Android特有Binder机制所以单独列出,这类耗时可采用减少或替代Binder调用等手段来优化。
引用参考:
课外补充引用:
文章学习来源:
- 【Android 客户端专场 学习资料三】第四届字节跳动青训营(# 第七节:初识性能优化及工具)
感谢以上作者的文章,今天的学习收获满满!!Thanks and HappyCoding!