线下场景-UI(systrace + perfetto)

线下场景我们能直接连接设备debug,所以监控纬度很多,我们从4个方面入手(就像是中医的望闻听切)来介绍相关监控工具的使用。(如果你已经很熟悉的话,可以直接跳过)
1.UI
2.CPU
3.内存
4.整体
在下面的章节会逐一介绍,本节先介绍UI。
本节我们主要介绍可以用来分析UI的工具 systrace和Perfetto。

这两个工具都是Android系统提供的系统追踪工具,可追踪/监控应用各个方面的数据,包括CPU、内存、view、IO等,其中Perfetto是Android 10(API 29)推出的,用来取代systrace。但鉴于目前Android10的份额有限,我们这两个都介绍下。

一.systrace
具体使用有两种方式,第一种图形化方式,Android Device Monitor(SDK tools中的monitor.bat):
在这里插入图片描述
点击红框处按钮弹出对话框,对想监控的指标进行勾选,然后生成trace.html,再用Chrome浏览器打开查看数据。
在这里插入图片描述
但这种方式经常有问题,打开后空白,也没有错误提示。所以不推荐,我们使用第二种方式。

第二种方式,使用python命令。有两个前提工作:
(1) 首先安装python2.7版本(必须为这一版本)
(2) 配置环境变量(这里不再展开说明)

其次,应用还必须是可debug的,设备可能还需要root。
环境准备好后, 在cmd中进入你的android sdk \platform-tools\systrace目录,接着输入命令即可。

命令的格式是这样的:
systrace.py [options] [categories]
(关于options和categories所有属性以及注意事项后面备注会写)

先直接举个简单的例子:

systrace.py -t 5 -o systrace.html view

意思是记录整个设备的view绘制信息,持续5S,输出到systrace.html文件中。
在这里插入图片描述
用Chrome打开这个html(其它浏览器也可打开,但显示不够完整)。
打开后,是这样的,因为是捕获整个系统的,所以有很多进程,需要手动选择自己的那个进程。
在这里插入图片描述
选定了自己的进程后,信息还是很多,有种无从下手的感觉
不用担心,右侧面板的alerts会给我们一些提示(不一定是问题,但可以是优化方向)。
在这里插入图片描述
可以看到,有三种提示类型,分别是过渡测量/布局、长绘制、过大bigmap。我们选中第一个Expensive measure/layout,可以看到左侧有几个圆圈标红,其余的都变成了黑灰色。每个圆圈里面有个F,这是frame的缩写,代表每一帧的绘制。颜色越深绘制时间越长,正常的要在16ms以内。
在这里插入图片描述
我们可以使用键盘的ws ad键进行放大、缩小,和左移右移,M键查看(聚焦)。
我们挑选第一个F,再按m键查看,可以看到这一帧足足花费了324ms。
在这里插入图片描述
更近一步的查看,我们只需要关注UI Thread和Render Thread这两个即可。
UI Thread显然就是主线程了,它负责处理进程 Message、处理 Input 事件、处理 Animation 逻辑、处理 Measure、Layout、Draw ,更新 DisplayList ,但是不涉及 SurfaceFlinger;Render Thread称之为渲染线程,负责渲染渲染相关的工作(基于硬件加速)。
在Android 5.0之前,这些操作都是在主线程进行的,为了减轻主线程的负担,之后进行了独立。
Android系统的UI从绘制到显示到屏幕是分两步进行的:第一步是在Android应用程序进程这一侧进行的;第二步是在SurfaceFlinger进程这一侧进行的。第一步将UI绘制到一个图形缓冲区中,然后交给第二步来进行合成及显示。
按W键放大视图,可以看到UI Thread中有熟悉的layout 方法(序号1),我们单击它,下方(序号2)处给出了alert的提示:layout花费大量时间,虽然wall duration(持续时间)只有1.494ms, 然而当我们想弄清楚到底是哪个view或者是具体的代码导致的,这里的信息就不够了。
在这里插入图片描述
不过systrace提供了代码标记的方法,在我们觉得有可能会出现卡顿的地方打上标记,这样在视图里就可以展现。具体如下:
//代码开始
Trace.beginSection(“tag”);
//代码结束
Trace.endSection();
开始和结束必须在同一线程中。
为了支持这个标记功能,在py命令里还要加上“-a 包名”
为了方便查找,我在tag后加了三个*号,可以直接在序号1处填入你的tag进行搜索,并且可以跳转(需要配合缩放移动),在序号2处可以看到我们添加标记的那段代码的执行时间,这样就有一个直观的认识了。
在这里插入图片描述
二.Perfetto
Perfetto 是 Android 10 中引入的全新平台级跟踪工具,用来替换systrace。不仅适用于 Android、还适用Linux 和 Chrome的。

它的入口就是个网页:https://ui.perfetto.dev (网络有时候很差)

基本上可分为三种使用方式:
1.直接debug
2.设备上生成 .perfetto-trace文件导入查看
3.通过adb命令生成文件导入查看

1.直接debug,设备得是android 10及以上的:
在这里插入图片描述
我们需要把GPU里的两个开关打开。然后点击recording开始记录即可,默认10S。然后自动生成结果页面。

在这里插入图片描述
2.在设备上记录,”开发者选项”-”系统跟踪”,不过有的Android 10手机上并没有此选项,比如华为手机。
在这里插入图片描述
类别里我们选择和UI相关的即可
在这里插入图片描述
然后选择快捷设置图标(会在通知栏上显示状态)
在这里插入图片描述
最后开始记录
在这里插入图片描述
在这里插入图片描述

记录完毕后,用adb命令导出即可:
adb pull /data/local/traces/.
然后如下图所示,在Perfetto平台导入即可。
在这里插入图片描述
2.adb 命令生成
先生成文件在设备上

adb shell perfetto --config :test --out /data/misc/perfetto-traces/trace

在这里插入图片描述
然后再从设备上pull下来

adb pull /data/misc/perfetto-traces/trace

在这里插入图片描述

这里只是最简单的命令,详细可参考;
https://developer.android.google.cn/studio/command-line/perfetto

导入后的结果页面长这样,比较友好,使用方式和原理基本与systrace一样,我们就不做过多的介绍了。
在这里插入图片描述
更多了解下还是看看官网吧:
https://perfetto.dev/

三.代码
可以用Window().addOnFrameMetricsAvailableListener来打印出每帧的耗时情况,仅支持android 7.0以上的设备

boolean isListener = true;
    private void onFrameListener() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            getWindow().addOnFrameMetricsAvailableListener(new Window.OnFrameMetricsAvailableListener() {
                @Override
                public void onFrameMetricsAvailable(Window window, FrameMetrics frameMetrics, int i) {
                    Log.d("onFrameListener", "measure + layout=" + frameMetrics.getMetric(FrameMetrics.LAYOUT_MEASURE_DURATION) / 1000000 + "ms" +
                            "    delay=" + frameMetrics.getMetric(FrameMetrics.UNKNOWN_DELAY_DURATION) / 1000000 + "ms" +
                            "    anim=" + frameMetrics.getMetric(FrameMetrics.ANIMATION_DURATION) / 1000000 + "ms" +
                            "    touch=" + frameMetrics.getMetric(FrameMetrics.INPUT_HANDLING_DURATION) / 1000000 + "ms" +
                            "    draw=" + frameMetrics.getMetric(FrameMetrics.DRAW_DURATION) / 1000000 + "ms" +
                            "    total=" + frameMetrics.getMetric(FrameMetrics.TOTAL_DURATION) / 1000000 + "ms");
                    if (!isListener) {
                        getWindow().removeOnFrameMetricsAvailableListener(this);
                    }
                }
            }, new Handler());
        }
    }

使用方式就是给window加个监听,当不需要的时候,移除监听即可。
打印结果如下:
在这里插入图片描述
当你在操作页面的时候,可以实时打印出结果,还是挺方便的。这样就将页面的流畅度通过数字量化了,不再是个主观上的”感觉”。

除了这一种方法外,还有其它的方法,可参考:
https://www.jianshu.com/p/c647d090e9c8

UI总结:
本节主要介绍了监控UI的一些工具。
systrace使用门槛较高,需要有一定的底层知识才能分析,并且提供的信息不够精确,不好定位且打标签有代码侵入性。
perfetto对版本的要求比较高,大部分的低版本设备都无法使用。
一般需要结合其它工具来一起使用,比如我们已经很熟悉的 过度绘制、GPU呈现模式分析、Hierarchy Viewer,Layout Inspector等等。很多大厂如字节跳动的内部监控工具也是基于systrace做的。我们这里仅仅只能提供入门讲解。
除了系统提供的工具,adb命令也可以监控到UI的一些信息,比如dumpsys,它可以获取所有系统服务的诊断输出。例如:“adb dumpsys gfxinfo 包名” 来查看帧的耗时数据。不过页面不是很友好,上手成本比较高。
其实只要能定位到问题所在其实就好办,很多时候就是难在不好定位。以上这些工具就是帮我们定位的。定到位后再去开个药方针对性治疗,关于怎么治,这里也不再展开说了,无外乎就是那些 不要在draw方法里耗时操作,提前渲染好需要展示的资源(错峰/延时加载)、layout不要嵌套太多、循环中不要新建过多对象等等。

AS自带的Layout Inspector布局检查器,我们就不过多介绍了。
官方介绍:https://developer.android.google.cn/studio/debug/layout-inspector#layout-inspector
另外还有很多开源工具,大家可以了解下:
在这里插入图片描述

最后,强烈推荐查看谷歌”亲爸爸”的关于UI性能优化的文章:
https://developer.android.google.cn/training/testing/performance

备注:
1.systrace命令的补充说明:
systrace.py [options] [categories]
[options]:
-a <package_name>:这个选项可以开启指定包名App中自定义Trace Label的Trace功能。也就是说,如果你在代码中使用了Trace.beginSection(“tag”), Trace.endSection;默认情况下,你的这些代码是不会生效的,因此,这个选项一定要开启!
-t N:用来指定Trace运行的时间
-l:这个用来列出你分析的那个手机系统支持的Trace模块;
-o FILE:指定trace数据文件的输出路径,如果不指定就是当前目录的trace.html。
[category]:
常用的有这几项:
sched: CPU调度的信息,非常重要;你能看到CPU在每个时间段在运行什么线程;线程调度情况,比如锁信息。
gfx:Graphic系统的相关信息,包括SerfaceFlinger,VSYNC消息,Texture,RenderThread等;分析卡顿非常依赖这个。
view: View绘制系统的相关信息,比如onMeasure,onLayout等;对分析卡顿比较有帮助。
am:ActivityManager调用的相关信息;用来分析Activity的启动过程比较有效。
dalvik: 虚拟机相关信息,比如GC停顿等。
binder_driver: Binder驱动的相关信息,如果你怀疑是Binder IPC的问题,不妨打开这个。
core_services: SystemServer中系统核心Service的相关信息,分析特定问题用

2.线程状态查看
如下图所示位置会显示线程的执行情况:
绿色:Running 线程正在完成与进程相关的工作或正在响应中断。
蓝色:Runnable 线程可以运行但当前没有安排。
白色:Sleeping 线程没有工作要做,可能是因为线程在互斥锁上被阻塞。
橙色:Uninterruptable sleep(不间断的睡眠) 线程在I/O上被阻塞或等待磁盘操作完成。
紫色:Interruptable sleep(可以中断睡眠) 线程在另一个内核操作(通常是内存管理)上被阻塞。

3.相关时间解释
Wall Duration 持续时间
CPU Duration CPU耗时
Self Time 自身方法耗时(不包含其调用方法
CPU Self Time 自身方法CPU执行时间

扩展:
1.Systrace中典型的一帧绘制流程
在这里插入图片描述

这张图对应的工作流程如下:
1.主线程处于 Sleep 状态,等待 Vsync 信号
2.Vsync 信号到来,主线程被唤醒,Choreographer 回调 FrameDisplayEventReceiver.onVsync 开始一帧的绘制
3.处理 App 这一帧的 Input 事件(如果有的话)
4.处理 App 这一帧的 Animation 事件(如果有的话)
5.处理 App 这一帧的 Traversal 事件(如果有的话)
6.主线程与渲染线程同步渲染数据,同步结束后,主线程结束一帧的绘制,可以继续处理下一个 Message(如果有的话,IdleHandler 如果不为空,这时候也会触发处理),或者进入 Sleep 状态等待下一个 Vsync
7.渲染线程首先需要从 BufferQueue 里面取一个 Buffer(dequeueBuffer) , 进行数据处理之后,调用 OpenGL 相关的函数,真正地进行渲染操作,然后将这个渲染好的 Buffer 还给 BufferQueue (queueBuffer) , SurfaceFlinger 在 Vsync-SF 到了之后,将所有准备好的 Buffer 取出进行合成。

2.systrace快捷键使用
快捷键的使用可以加快查看 Systrace 的速度,下面是一些常用的快捷键
W : 放大 Systrace,放大可以更好地看清局部细节
S : 缩小 Systrace,缩小以查看整体
A : 左移
D : 右移
M : 高亮选中当前鼠标点击的段(这个比较常用,可以快速标识出这个方法的左右边界和执行时间,方便上下查看)

鼠标模式快捷切换 : 主要是针对鼠标的工作模式进行切换,默认是 1,也就是选择模式,查看 Systrace 的时候,需要经常在各个模式之间切换,所以点击切换模式效率比较低,直接用快捷键切换效率要高很多

数字键1 : 切换到 Selection 模式,这个模式下鼠标可以点击某一个段查看其详细信息,一般打开 Systrace 默认就是这个模式,也是最常用的一个模式,配合 M 和 ASDW 可以做基本的操作
数字键2 : 切换到 Pan 模式,这个模式下长按鼠标可以左右拖动, 有时候会用到
数字键3 : 切换到 Zoom 模式,这个模式下长按鼠标可以放大和缩小,有时候会用到
数字键4 : 切换到 Timing 模式,这个模式下主要是用来衡量时间的,比如选择一个起点,选择一个终点,查看起点和终点这中间的操作所花费的时间。

参考:
systrace常识:
https://blog.csdn.net/f2006116/article/details/107581327

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值