Android应用性能优化最佳实践.2.2 性能分析工具

简介:

2.2 性能分析工具


从前一节可以看到,Android系统在4.1以后从框架上解决了由于系统问题导致的卡顿现象,但在实际的使用过程中,在用户的感受上,卡顿仍然是应用开发中主要面临的问题,而原因从上一节的分析中也知道本质是VSync信号到来时,不能及时处理绘制事件导致,本节先抛出以下两个问题:

1)应用层做了什么会导致VSync事件不能及时处理?

2)卡顿能监控吗?

性能问题并不容易复现,也不好定位,光从几个场景不能完全覆盖所有的问题,因此在做性能优化时,最直接有效的方法,就是尽量复现存在性能问题的场景,并监控此过程中程序的执行流程,如果能够方便地分析程序中函数的调用关系和执行时间,自然也就很容易找出性能瓶颈。

分析问题和确认问题是否解决,都借助了相应的调试工具,比如查看Layout层次的Hierarchy View、Android系统上带的GPU Prof?ile工具和静态代码检查工具Lint等。这些工具对性能优化都起到非常重要的作用。本节将介绍这些工具和另外两个性能优化非常重要的工具:TraceView和Systrace。这两个工具除了在UI上,对于在后面将要讲到的启动优化、动画优化等上都是很重要的工具,可以说大部分的性能分析都离不开这几个工具,接下来学习几个常用的与流畅度优化相关的工具的使用方法,在后面实际的优化方案中也会介绍其他辅助工具。

2.2.1 卡顿检测工具

要做性能优化,就非常有必要借助于一系列辅助工具,Android提供了多个开发辅助工具,在性能调优过程中非常重要,下面介绍几个常用的工具,在后面的具体优化过程中会多次使用到。

我们已经知道,从应用层绘制一个页面(View),主要有三个过程:CPU准备数据→GPU从数据缓存列表获取数据→Display设备绘制,这三个过程的耗时可以通过一个手机开发辅助工具查看:Prof?ile GPU Rendering。Prof?ile GPU Rendering是Android 4.1系统开始提供的一个开发辅助功能,在设置中打开开发者选项,如图2-12所示。

Prof?ile GPU Rendering功能特点如下:

它是一个图形监测工具,能实时反应当前绘制的耗时。

横轴表示时间,纵轴表示每一帧的耗时(单位为ms)。

随着时间推移,从左到右的刷新呈现。

提供了一个标准的耗时,如果高于标准耗时,表示当前这一帧丢失。

如果设置中没有开发者选项,可以通过设置页面中的“关于”选项,单击版本号七次即可打开开发者选项,在后面的章节中还会使用到开发者选项中的其他辅助工具。

打开Prof?ile GPU Rendering后可以看到实时刷新的彩色图,如图2-13所示。每一根竖线表示一帧,由多个颜色组成,不同颜色的解释如下:

图2-12 打开Prof?ile GPU rendering 图2-13 Prof?ile GPU rendering

每一条柱状图都由4种颜色组成:红、黄、蓝、紫,这些线对应每一帧在不同阶段的实际耗时。

蓝色代表测量绘制的时间,它代表需要多长时间去创建和更新DisplayList。在Android中,一个视图在进行渲染之前,它必须被转换成GPU熟悉的格式,简单来说就是几条绘图命令,蓝色就是记录了在屏幕上更新视图需要花费的时间,也可以理解为执行每一个View的onDraw方法,创建或者更新每一个View的Display List对象。在蓝色的线很高时,有可能是因为需要重新绘制,或者自定义视图的onDraw函数处理事情太多。

红色代表执行的时间,这部分是Android进行2D渲染Display List的时间,为了绘制到屏幕上,Android需要使用OpenGl ES的API接口来绘制Display List,这些API有效地将数据发送到GPU,最终在屏幕上显示出来。当红色的线非常高时,可能是由重新提交了视图而导致的。

橙色部分表示处理时间,或者是CPU告诉GPU渲染一帧的地方,这是一个阻塞调用,因为CPU会一直等待GPU发出接到命令的回复,如果柱状图很高,就意味着GPU太繁忙了。

紫色段表示将资源转移到渲染线程的时间,只有Android 4.0及以上版本才会提供。

在实际开发中,从图上虽然可以看到绘制的时间,但对不便于进行数据分析,比如进入某一个页面,柱形图虽然实时绘制出来,但不能更好地分析,这里可以通过:adb shell dumpsys gfxinfo com.**.**(包名)把具体的耗时输出到日志中来分析。

任何时候超过绿线(警戒线,对应时长16ms),就有可能丢失一帧的内容,虽然对于大部分应用来说,丢失几帧确实感觉不出卡顿,但保持UI流畅的关键就在于让这些垂直的柱状条尽可能地保持在绿线下面。

GPU Prof?ile工具能够很好地帮助你找到渲染相关的问题,但是要修复这些问题就不是那么简单了。需要结合另一个耗时工具和代码来具体分析,找到性能的瓶颈,并进行优化。在GPU Prof?ile Render发现有问题的页面后,可以通过另外一个工具Hierarchy Viewer来查看页面的布局层次和每个View所花的时间,在后面的布局优化章节,将通过实例来讲解和学习使用方法。

2.2.2 TraceView

TraceView是AndroidSDK自带的工具,用来分析函数调用过程,可以对Android的应用程序以及Framework层的代码进行性能分析。它是一个图形化的工具,最终会产生一个图表,用于对性能分析进行说明,可以分析到应用具体每一个方法的执行时间,使用可以非常直观简单,分析性能问题很方便。

1.?使用方法

在使用TraceVeiw分析问题之前需要得到一个*.trace的文件,然后通过TraceView来分析trace文件的信息,trace文件的获取有两种方式:

(1)在DDMS中使用

1)连接设备。

2)打开应用。

3)打开DDMS(若在Android Studio中则先打开Android Device Monitor)。

4)单击Strart Method Prof?iling按钮,如图2-14所示。

 

图2-14 在DDMS中打开TraceView

5)在应用中操作需要监控的点,比如进入一个Activity或者滑动一个列表,完成后单击Stop Method Prof?iling按钮,如图2-15所示。

 

图2-15 结束一次TraceView

6)结束会自动跳转到TraceView视图。

这种方法使用方便,但监控范围不够精确,如果需要精确监控某一个路径,就需要使用下一个方法:在代码中加入调试语句保存Trace文件。

(2)代码中加入调试语句保存trace文件

有时在开发过程中不好复现的问题,需要在关键的路径上获取TraceView数据,在测试时复现此问题后直接拿到Trace文件查看对应的数据。这时可以在代码中使用TraceView工具并生成对应的trace文件。在android.os.Debug类中提供了相应的方法,过程很简单步骤如下:

1)在需要开始监控的地方调用startMethodTracing()。

2)在需要结束监控的地方调用stopMethodTracing()。

3)系统会在SD卡中创建<trace-name>.trace文件。

4)使用traceveiw打开该文件进行分析。

调用代码如下:

// start tracing to "/sdcard/ui_performance.trace"

Debug.startMethodTracing("ui_performance");

// ...

// stop tracing

Debug.stopMethodTracing();

在应用程序中调用startMethodTracing()时,系统会在指定的路径上创建一个名为<trace_f?ilename>.trace文件。这个文件包含了方法名跟踪数据,以及与线程和方法名的映射表。然后系统开始缓存应用产生的跟踪数据,直到应用程序调用stopMethodTracing()结束,此时将其缓冲的数据写入输出文件中。如果系统达到最大缓存大小时,还没有调用stopMethodTracing(),系统会停止跟踪并发送一个通知。

在Android 4.4及更高版本中,可以通过基于采样的方法分析耗时情况,因为减少了分析Trace文件的次数,降低了IO读写,所以可以减少Trace工具在运行时对性能的影响,同时对分析结果也不会有很大的偏差。通过调用startMethodTracing()方法,就可以指定具体的采样间隔,定期采集样本数据分析。

在代码中使用此方法保存TraceView数据,不要忘记在应用中打开write to external storage权限(WRITE_EXTERNAL_STORAGE)。

2.?TraceView视图说明

Traceview视图分两部分,上半部分为时间片面板(Timeline Panel),下半部分为分析面板(Prof?ile Panel)。

时间片面板如图2-16所示。

 

图2-16 时间片面板

X轴表示时间消耗,单位为毫秒(ms),Y轴表示各个线程,每个线程中的不同方法使用了不同的颜色来表示,颜色占用面积越宽,表示该方法占用CPU时间越长。

时间片面板可以放大/缩小,也可以指定区域放到最大,方便查看具体的过程,一般优先选择放大耗时严重的区域。

分析面板(Prof?ile Panel)如图2-17所示。

 

图2-17 分析面板

分析面板看起来并不复杂,但需要理解各列数据的意义,每一列表示的意义如表2-1所示。

表2-1 分析面板参数意义

列  名 意  义

Name 所有的调用项,展开可以看到有的有Parent和Children子项,指被调用和调用

Inclusive 统计函数本身运行的时间+调用子函数运行的时间

incl inclusive时间占总时间的白分比

Exclusive 同级函数本身运行的时间

Excl 执行占总时间的白分比

Calls + Recur Calls / Total 该方法调用次数+递归次数

Cpu Time / Call 该方法耗时

Real Time / Call 实际时长

 

使用TraceView查看耗时,主要关注Calls + Recur Calls / Total和Cpu Time / Call这两个值,也就是关注调用次数多和耗时久的方法,然后优化这些方法的逻辑和调用次数,减少

耗时。

RealTime与cputime区别为:因为RealTime包括了CPU的上下文切换、阻塞、GC等,所以RealTime方法的实际执行时间要比CPU Time稍微长一点。

2.2.3 Systrace UI性能分析

在应用程序开发过程中,UI(用户界面)的流畅度是体验的核心,特别是在动画、跳转或者列表的滑动过程中,出现卡顿和无响应是非常影响用户体验的,要解决这些问题,首先要找到问题的原因,前面介绍的TraceView是分析性能的一款利器,下面再介绍一个分析应用程序UI性能的工具:Systrace。

Systrace是Android 4.1及以上版本提供的性能数据采样和分析工具。它可以帮助开发者收集Android关键子系统(如surfacef?linger、WindowManagerService等Framework部分关键模块、服务,View系统等)的运行信息,从而帮助开发者更直观地分析系统瓶颈,改进性能。Systrace的功能包括跟踪系统的I/O操作、内核工作队列、CPU负载等,在UI显示性能分析上提供很好的数据,特别是在动画播放不流畅、渲染卡等问题上。Systrace工具可以跟踪、收集、检查定时信息,可以很直观地查看CPU周期消耗的具体时间,显示每个线程和进程的跟踪信息,使用不同颜色来突出问题的严重性,并提供如何解决这些问题的建议。

由于Systrace是以系统的角度返回一些信息,并不能定位到具体耗时的方法,要进一步获取CPU满负荷运行的原因,就需要使用前面介绍过的工具Traceview。

1.?Systrace使用方法

Systrace的使用不复杂。但跟踪的设备必须是Android 4.1(API16)或更高版本。在4.3版本和4.3以前版本的使用上有些区别,后面会讲到。

4.3以前系统版本的设备需要打开Settings > Developer options > Monitoring > Enable traces。

(1)在DDMS上使用

在Eclipse和Android Studio中都可以在DDMS直接使用Systrace,其他IDE也能支持,且流程都相同,下面以Android Studio为例说明其使用流程。

1)打开Android Device Monitor,连接手机并准备需要抓取的界面。

2)单击Systrace按钮进入抓取前的设置,选择需要跟踪的内容(见图2-18):

3)手机上开始操作需要跟踪的过程(如滑动列表)。

4)到了设定好的时间后,生成Trace文件。

5)使用Chrome打开文件即可分析。

(2)使用命令行

使用命令行方式更灵活,速度更快,并且配置好后再使用能快速得到结果,在Android 4.3及更高版本的设备上使用Systrace时,可以省略设置跟踪类别标签来获取默认值,或者可以手动列入指定标签。命令如下:

$ cd android-sdk/platform-tools/systrace

$ python systrace.py --time=10 -o mynewtrace.html sched gfx view wm

其中参数设置对应的功能如表2-2所示。

表2-2 System参数命令

参数名 意  义

-h, --help 帮助信息

-o <FILE> 保存的文件名

-t N, --time=N 多少秒内的数据,默认为5秒,以当前时间点往后倒N秒时间

-b N, --buf-size=N 单位为千字节,限制数据大小

-k <KFUNCS> --ktrace=<KFUNCS> 追踪特殊的方法

-l, --list-categories 设置需要追踪的标签

-a <APP_NAME>, --app=<APP_NAME> 包名

--from-f?ile=<FROM_FILE> 创建报告的来源trace文件

-e <DEVICE_SERIAL>, --serial=<DEVICE_SERIAL> 设备号

 

其中categories中的标签比较多,可以从官方的文档上查询:http://developer.android.com/intl/zh-cn/tools/help/systrace.html

(3)应用中获取

Systrace不会追踪应用的所有工作,所以在有需求的情况下,需要添加要追踪的代码部分。在Android 4.3及以上版本的代码中,可以通过Trace类来实现这个功能。它能够让你在任何时候跟踪应用的一举一动。在获取Trace的过程中,即Trace.beginSection()与Trace.endSection()之间的代码工作会一直被追踪。

在代码中加入Trace跟踪需要注意以下两点:

在Trace被嵌套在另一个Trace中时,endSection()方法只会结束离它最近的一个beginSection(String),即在一个Trace的过程中是无法中断其他Trace的。所以要保证endSection()与beginSection(String)调用次数匹配。

Trace的begin与end必须在同一线程中执行。

下面这部分代码为使用Trace的例子,在整个方法中含有两个Trace块,可以根据需求定义更多的块,但都要成对出现,如果有开始块但没有结束块,会严重影响应用的性能。

public void ProcessPeople() {

    Trace.beginSection("ProcessPeople");

    try {

        Trace.beginSection("Processing Jane");

        try {

            // code for Jane task...

        } finally {

            Trace.endSection(); // ends "Processing Jane"

        }

        Trace.beginSection("Processing John");

        try {

            // code for John task...

        } finally {

            Trace.endSection(); // ends "Processing John"

        }

    } finally {

        Trace.endSection(); // ends "ProcessPeople"

    }

}

2.?分析Systrace报告

通过前面方法获取到的trace.html文件,需要使用Chrome打开,有一些常用的快捷键,定义如表2-3所示。

目前Systrace产生的trace文件只能使用Chrome打开,使用Chrome打开文件后如图2-19所示。

从图2-19中可以看到完整的数据,其中和UI绘制关系最密切的是Alerts和Frame两个数据,接下来重点介绍Alerts和Frame。

 

图2-19 Systrace Viewer

(1)Alerts

从图2-19可以看到,Alerts一栏标记了性能有问题的点,单击该点可以查看详细信息,在右边侧边栏还有一个Alerts框,单击可以查看每个类型的Alerts的数量,单击某一个Alert可以看到问题的详细描述。

(2)Frame

每个应用都有一行专门显示frame,每一帧就显示为一个绿色的圆圈。当显示为黄色或者红色时,它的渲染时间超过了16.6ms(即达不到60fps的水准)。使用W键放大,看看这一帧的渲染过程中系统到底做了什么,同时它会将任何它认为性能有问题的东西都高亮警告,并提示要怎么优化。如图2-19所示,在Frame栏有一个F帧(第二帧)黄色告警,从下面的问题详细描述可以看出,警告的主要原因是ListView的回收和重新绑定花费太多时间。在Systrace中也会提供一些对应链接,提供更多解释。

如果想知道UI线程怎么会花费这么多时间的话,就需要使用2.2.2节讲到的TraceView,来分析具体是哪些函数在消耗时间。

相关实践学习
部署Stable Diffusion玩转AI绘画(GPU云服务器)
本实验通过在ECS上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。
相关文章
|
1月前
|
开发框架 前端开发 Android开发
Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势
本文深入探讨了 Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势。这对于实现高效的跨平台移动应用开发具有重要指导意义。
175 4
|
24天前
|
JSON Java API
探索安卓开发:打造你的首个天气应用
在这篇技术指南中,我们将一起潜入安卓开发的海洋,学习如何从零开始构建一个简单的天气应用。通过这个实践项目,你将掌握安卓开发的核心概念、界面设计、网络编程以及数据解析等技能。无论你是初学者还是有一定基础的开发者,这篇文章都将为你提供一个清晰的路线图和实用的代码示例,帮助你在安卓开发的道路上迈出坚实的一步。让我们一起开始这段旅程,打造属于你自己的第一个安卓应用吧!
52 14
|
27天前
|
Java Linux 数据库
探索安卓开发:打造你的第一款应用
在数字时代的浪潮中,每个人都有机会成为创意的实现者。本文将带你走进安卓开发的奇妙世界,通过浅显易懂的语言和实际代码示例,引导你从零开始构建自己的第一款安卓应用。无论你是编程新手还是希望拓展技术的开发者,这篇文章都将为你打开一扇门,让你的创意和技术一起飞扬。
|
25天前
|
搜索推荐 前端开发 测试技术
打造个性化安卓应用:从设计到开发的全面指南
在这个数字时代,拥有一个定制的移动应用不仅是一种趋势,更是个人或企业品牌的重要延伸。本文将引导你通过一系列简单易懂的步骤,从构思你的应用理念开始,直至实现一个功能齐全的安卓应用。无论你是编程新手还是希望拓展技能的开发者,这篇文章都将为你提供必要的工具和知识,帮助你将创意转化为现实。
|
28天前
|
网络协议 Linux Android开发
深入探索Android系统架构与性能优化
本文旨在为读者提供一个全面的视角,以理解Android系统的架构及其关键组件。我们将探讨Android的发展历程、核心特性以及如何通过有效的策略来提升应用的性能和用户体验。本文不包含常规的技术细节,而是聚焦于系统架构层面的深入分析,以及针对开发者的实际优化建议。
48 1
|
1月前
|
前端开发 数据处理 Android开发
Flutter前端开发中的调试技巧与工具使用方法,涵盖调试的重要性、基本技巧如打印日志与断点调试、常用调试工具如Android Studio/VS Code调试器和Flutter Inspector的介绍
本文深入探讨了Flutter前端开发中的调试技巧与工具使用方法,涵盖调试的重要性、基本技巧如打印日志与断点调试、常用调试工具如Android Studio/VS Code调试器和Flutter Inspector的介绍,以及具体操作步骤、常见问题解决、高级调试技巧、团队协作中的调试应用和未来发展趋势,旨在帮助开发者提高调试效率,提升应用质量。
55 8
|
1月前
|
Android开发 开发者
Android性能优化——内存管理的艺术
Android性能优化——内存管理的艺术
|
25天前
|
Java Android开发 开发者
探索安卓开发:构建你的第一个“Hello World”应用
在安卓开发的浩瀚海洋中,每个新手都渴望扬帆起航。本文将作为你的指南针,引领你通过创建一个简单的“Hello World”应用,迈出安卓开发的第一步。我们将一起搭建开发环境、了解基本概念,并编写第一行代码。就像印度圣雄甘地所说:“你必须成为你希望在世界上看到的改变。”让我们一起开始这段旅程,成为我们想要见到的开发者吧!
33 0
|
1月前
|
Android开发 开发者 UED
安卓开发中自定义View的实现与性能优化
【10月更文挑战第28天】在安卓开发领域,自定义View是提升应用界面独特性和用户体验的重要手段。本文将深入探讨如何高效地创建和管理自定义View,以及如何通过代码和性能调优来确保流畅的交互体验。我们将一起学习自定义View的生命周期、绘图基础和事件处理,进而探索内存和布局优化技巧,最终实现既美观又高效的安卓界面。
42 5
|
1月前
|
JSON Java Android开发
探索安卓开发之旅:打造你的第一个天气应用
【10月更文挑战第30天】在这个数字时代,掌握移动应用开发技能无疑是进入IT行业的敲门砖。本文将引导你开启安卓开发的奇妙之旅,通过构建一个简易的天气应用来实践你的编程技能。无论你是初学者还是有一定经验的开发者,这篇文章都将成为你宝贵的学习资源。我们将一步步地深入到安卓开发的世界中,从搭建开发环境到实现核心功能,每个环节都充满了发现和创造的乐趣。让我们开始吧,一起在代码的海洋中航行!