Android性能优化 -- Systrace工具

Systrace简介
    一般来说,我们的机器以60帧/秒显示时,用户会感觉机器很流畅,如果显示时出现丢帧的情况,需要知道当前整个系统所处的状态,这个时候Systrace便是最佳的工具选择。

    Systrace是Android4.1中新增的性能数据采样和分析工具。它可帮助开发者收集Android关键子系统(如Surfaceflinger、WindowManagerService等framework部分关键模块、服务)的运行信息,从而帮助开发者更直观的分析系统瓶颈,改进性能。

    Systrace在分析一些显示(performence)的问题上特别有用,如有用画图慢,显示动作或动画时变形等。

    Systrace的功能包括跟踪系统的I/O操作、内核工作队列、CPU负载以及Android各个子系统的运行状况等。在Android平台中,它主要由3部分组成:

    1. 内核部分:Systrace利用了Linux Kernel中的ftrace功能。所以要使用Systrace的话,必须开启kernel中和ftrace相关的模块。

    2. 数据采集部分:Android定义了一个Trace类。应用程序可利用该类把统计信息输出给ftrace。同时,Android还有一个atrace程序,它可以从ftrace中读取统计信息然后交给数据分析工具来处理。

    3. 数据分析工具:Android提供了一个systrace.py(Python脚步文件,位于Android SDK目录/tools/systrace中,其内部将调用atrace程序)用来配置数据采集的方式(如采集数据的标签、输出文件名等)和收集ftrace统计数据并生成一个结果网页文件供用户查看。

    本质上,Systrace是对Linux Kernel中ftrace的封装,应用程序需要利用Android提供的Trace类来使用Systrace。

抓取systrace
    有三种方式抓取systrace。

systrace.py工具
    首先,在手机端准备好你需要分析的过程的环境;比如假设你要分析App的冷启动过程,那就先把App进程杀掉,切换到Launcher中有你的App图标的那个页面,随时准备点击图标启动进程;假设你要分析某个Activity的卡顿情况,那就先在手机上进入到上一个Activity,随时准备点按钮切换到待分析的Activity中。因为Systrace没办法自由地控制开始和结束(下面有一个办法可以缓解),而trace得到的数据有可能非常多,因此我们需要手工缩小需要分析的数据集合;不然你可能被一堆眼花缭乱的数据和图像弄得晕头转向,然后什么有用的结论也分析不出来。
    然后,打开PC端的命令行;进入systrace的目录,也即(假设$ANDROID_HOME是你Android SDK的根目录):   

cd $ANDROID_HOME/platform-tools/systrace。

    systrace命令行的用法如下:

python systrace.py [options] [category1] [category2] ... [categoryN]
    使用上面的命令需要安装Python。其中,“[options]”是一些命令参数;“[category]”等是你感兴趣的系统模块,比如view代表View系统(包含绘制流程),am代表ActivityManager(包含Activity的创建过程等)。分析不同的问题,可以选择不同的你感兴趣的模块。

示例如下:

cd android-sdk/platform-tools/systrace
python systrace.py --time=10 -o mynewtrace.html sched gfx view wm
    'systrace.py',这个脚本就是通过adb给手机发送了手机trace的通知;与此同时,切换到手机上进行你需要分析的操作,比如点击Launcher中APP的Icon启动APP。经过你指定的时间(--time=10,指定时间为10秒)后,就会有trace数据生成在当前目录(systrace所在目录),默认是‘trace.html’,上面使用‘-o mynewtrace.html’指定了生成的文件名;用Chrome浏览器打开即可。

options
    options的取值如下:

options    描述
-o < FILE >    输出的目标文件
-t N, –time=N    执行时间,默认5s
-b N, –buf-size=N    buffer大小(单位kB),用于限制trace总大小,默认无上限
-k < KFUNCS >,–ktrace=< KFUNCS >    追踪kernel函数,用逗号分隔
-a < APP_NAME >,–app=< APP_NAME >    追踪应用包名,用逗号分隔
–from-file=< FROM_FILE >    从文件中创建互动的systrace
-e < DEVICE_SERIAL >,–serial=< DEVICE_SERIAL >    指定设备
-l, –list-categories    列举可用的tags
category
    category取值如下:

category    描述
gfx    Graphics
input    Input
view    View System
webview    WebView
wm    Window Manager
am    Activity Manager
sm    Sync Manager
audio    Audio
video    Video
camera    Camera
hal    Hardware Modules
app    Application
res    Resource Loading
dalvik    Dalvik VM
rs    RenderScript
bionic    Bionic C Library
power    Power Management
sched    CPU Scheduling
irq IRQ    Events
freq    CPU Frequency
idle    CPU Idle
disk    Disk I/O
mmc    eMMC commands
load    CPU Load
sync    Synchronization
workq    Kernel Workqueues
memreclaim    Kernel Memory Reclaim
regulators    Voltage and Current Regulators
    这里看下几个比较常用的模块:

    sched:CPU调度的信息,非常重要;你能看到CPU在每个时间段在运行什么线程;线程调度情况,比如锁信息。

    gfx:Graphic系统的相关信息,包括SurfaceFlinger,VSYNC消息,Texture,RenderThread等;分析卡顿非常依赖这个。

    view:View绘制系统的相关信息,比如onMeasure,onLayout等;对分析卡顿比较有帮助。

    am:ActivityManager调用的相关信息;用来分析Activity的启动过程比较有效。

    dalvik: 虚拟机相关信息,比如GC停顿等。

    binder_driver:Binder驱动的相关信息,如果你怀疑是Binder IPC的问题,不妨打开这个。

    core_services:SystemServer中系统核心Service的相关信息,分析特定问题用。

DDMS
      可以使用Eclipse或者Android Studio集成开发工具,切换到DDMS,如果是在Android Studio中,双击shift按钮,弹出搜索框,输入Android Device Monitor,弹出DDMS窗口;点击devices,点击Systrace按钮:

上面图中最后一个图标,点击后弹出如下图:

 
    
    补充说明:

Destionation file :trace输出的文件路径。
Trace duration : 配置抓取systrace的时间,通常设置5秒,并在5秒内重现问题,时间太短会导致问题重现时没有被抓到,时间太长会导致Java Heap不够而无法保存,因此在能抓到问题点的情况下,时间越小越好。
Trace Buffer Size : Buffer Size是存储systrace的size,同样的,太小会导致信息丢失,时间太长会导致Java Heap不够而无法保存,建议20480。
Enable Application Traces from :如果用户有自己在应用程序中加入自己的systrace log:
Trace.beginSection("newInstance");
Trace.endSection();
那么此处必须选择这个应用对应的进程名字,否则新加的systrace log不会被抓到。
自定义systrace
    systrace没有办法在代码中控制Trace运行的开始和结束,那么,如果们要分析App的启动性能,我点了桌面图标,把Trace时间设置为10s,我怎么知道这10s中,哪段时间是我App的启动过程?如果不知道我们需要分析的时间段,那后续不是扯淡么?

    我们可以用自定义Trace Label解决;有时候为了debug方便,那么我们需要自己在apk或者framework层添加trace信息。比如我们觉得Fragment的onCreateView过程有问题,那就在`onCreateView` 中加上代码:

public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
            Bundle savedInstanceState) {
    Trace.beginSection("Fragement_onCreateView");
    // .. 其他代码
    // ...
    // .. 结束处
    Trace.endSection();
}
    这样,在Trace的分析结果中就会带上`Fragement_onCreateView` 这个过程的运行时间段信息(当然你得开启 -a 选项!),如下:


    我们可以在任意自己感兴趣的地方添加自定义的Label;一般来说,分析过程就是,你怀疑哪里有问题,就在那个函数加上Label,运行一遍抓一个Trace,看看自己的猜测对不对;如果猜测正确,进一步加Label缩小范围,定位到具体的自定义函数,函数最终调用到系统内部,那就开启系统相关模块的Trace,继续定位;如果猜测错误,那就转移目标,一步步缩小范围,直至问题收敛。

    上面我们说的是debugable状态的APP,那么对于非Debug的APP该如何分析呢?

    我们可以手动开启App的自定义Label的Trace功能,方法也很简单,调用一个函数即可;但是这个函数是SDK @hide的,我们需要反射调用:

Class<?> trace = Class.forName("android.os.Trace");
Method setAppTracingAllowed = trace.getDeclaredMethod("setAppTracingAllowed", boolean.class);
setAppTracingAllowed.invoke(null, true);
    把这段代码放在Application的`attachBaseContext` 中,这样就可以手动开启App自定义Label的Trace功能,在非debuggable的版本中也适用!
APP层
    Android SDK中提供了`android.os.Trace#beginSection`和`android.os.Trace#endSection` 这两个接,我们可以在代码中插入这些代码来分析某个特定的过程:

import android.os.Trace;
Trace.beginSection(String sectionName)
Trace.endSection()
    然后通过指令:python systrace.py --app=sectionName 指定APK,或者通过DDMS选择指定APK,抓取systrace分析。
Java framework层
import android.os.Trace;
Trace.traceBegin(long traceTag, String methodName)
Trace.traceEnd(long traceTag)
    Java framework层可以使用上面代码,抓取systrace分析。
Native framework层
#include <cutils/trace.h>
ATRACE_CALL()
    native framework层可以使用上面代码,最好在函数开头声明定义,抓取systrace分析。
systrace分析
    生成trace.html 文件后,直接在浏览器中打开就可以。

我们可以看到此界面的Frame的圆圈会显示三种颜色,绿,黄,红。一般红色就是有问题的,要优化的地方。

    我们可以看到此界面的Frame的圆圈会显示三种颜色,绿,黄,红。一般红色就是有问题的,要优化的地方。

    m可以显示选中方法的时间。

    Systrace会自动分析信息,将性能问题直接以alerts的方式高亮显示,我们只要修改这些alerts就可以。

    我们可以看到Alert的详细信息,描述和建议。这个Alert是可以定位到有问题的方法。如果我们想要知道方法的更详细信息,我们可以结合Traceview来解决问题。

快捷操作
导航操作
导航操作    作用
w    放大,[+shift]速度更快
s    缩小,[+shift]速度更快
a    左移,[+shift]速度更快
d    右移,[+shift]速度更快
常用操作
常用操作    作用
f    放大当前选定区域
m    标记当前选定区域
v    高亮VSync
g    切换是否显示60hz的网格线
0    恢复trace到初始态,这里是数字0而非字母o
一般操作
一般操作    作用
h    切换是否显示详情
/    搜索关键字
enter    显示搜索结果,可通过← →定位搜索结果
`    显示/隐藏脚本控制台
?    显示帮助功能
    另外,按住alt键,再滚动鼠标滚轮能实现放大/缩小功能。
实例例证可参考:Systrace的工作原理及例子解读

性能优化有哪些好的资料推荐?
Android性能优化典范,官方推出,必属精品。不仅仅告诉你哪里有问题,更告诉你为什么!
胡凯的博客,翻译了关于Android性能优化典范的内容,不想看视频的话可以参考博客。不过官方的典范及翻译都是偏理论性,需要自己去实践。
官方文档,不管是Training模块还是API模块,都藏了很多干货。
《移动App性能评测与优化》,腾讯TMQ专项测试团队的大作,深入底层,追本溯源,精益求精,带给人技术上提升的同时更端正做技术的态度,强烈推荐!
————————————————
版权声明:本文为CSDN博主「Kitty_London」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/kitty_landon/article/details/79192377

发布了56 篇原创文章 · 获赞 10 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/GJQI12/article/details/104491309