Android性能优化 -- Systrace工具

2023-05-16

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按钮:


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

 
    http://maoao530.github.io/img/archives/ddms-capture-systrace.png

    补充说明:

  • 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的工作原理及例子解读

性能优化有哪些好的资料推荐?

  1. Android性能优化典范,官方推出,必属精品。不仅仅告诉你哪里有问题,更告诉你为什么!
  2. 胡凯的博客,翻译了关于Android性能优化典范的内容,不想看视频的话可以参考博客。不过官方的典范及翻译都是偏理论性,需要自己去实践。
  3. 官方文档,不管是Training模块还是API模块,都藏了很多干货。
  4. 《移动App性能评测与优化》,腾讯TMQ专项测试团队的大作,深入底层,追本溯源,精益求精,带给人技术上提升的同时更端正做技术的态度,强烈推荐!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android性能优化 -- Systrace工具 的相关文章

  • 查看寻呼机 - 使用静态变量以编程方式滑动到下一页

    我想在我的 ViewPager 中以编程方式制作幻灯片 我的问题是 滑动事件是由放置在 ViewPager 保存的片段内部的按钮调用的 我知道代码 viewpager setCurrentItem int index 现在我的想法是使 Vi
  • 在代码中旋转按钮(或其中的文本)

    我必须通过编码随机旋转按钮 或里面的文本 它是相同的 API级别低于11是否有button setRotate x 好吧 看了一下 答案是 很复杂 您可以使用旧的动画框架旋转按钮 例如像这样 Button button Button fin
  • 如何在 Android 应用程序中单击按钮时打开 Gmail Compose?

    当我的 Android 应用程序中单击按钮时 我尝试打开 Gmail 撰写屏幕 我需要 Google 提供的 API 密钥吗 或者我需要在按钮 onClickListener 中做什么 任何形式的见解都非常值得赞赏 正如 JeffC 指出的
  • FLAG_ACTIVITY_REORDER_TO_FRONT 被忽略

    我有一个包含项目列表的 FragmentActivity 当应用程序处于后台时 可以推送该项目列表 发生这种情况时 我想创建一个状态栏通知并提醒用户更新 当用户单击通知时 活动应重新排序到前面并显示在屏幕上 同时在列表底部显示新项目 所以我
  • 在后台服务中持续获取位置更新

    我正在开发需要在后台服务中持续获取位置更新的应用程序 我已经使用了它正在使用的后台粘性服务 但是 即使我添加了启动广播并在那里启动了服务 启动完成后服务也没有启动 服务启动并立即被杀死 另外 这不适用于奥利奥 服务在应用程序关闭几分钟后停止
  • 在 Android 中始终以横向模式打开相机

    在我的 Android 应用程序中 单击按钮后我希望相机以横向模式打开 即使我将手机旋转为纵向模式 相机也应始终处于横向模式或纵向模式 使用此代码在横向模式下打开相机 Intent cameraIntent new Intent Media
  • 更改 Android 中的媒体音量?

    我可以更改媒体音量吗 如何 到目前为止我用过这个 setVolumeControlStream AudioManager STREAM MUSIC 但有一个搜索栏并且想要更改媒体音量 而不是铃声音量 那么有人可以告诉我如何更改媒体音量onC
  • 如何更改对话框片段内的片段

    我想做一个空的DialogFragment with a LinearLayout然后更改里面的片段LinearLayout 例如 第一个片段是 3 个按钮 facebook google 电子邮件登录 的登录 当有人按下电子邮件时 第 2
  • 如何在android中画一条曲线?

    我是 Android 新手 正在开发一个关于绘制线条的示例项目 我想画一条连接两点的曲线或高架线 x1 y1 and x2 y2 我试过canvas drawArc 方法 但是RectF内的值drawArc方法只是圆的 x y 中心点 它在
  • Android:BATTERY_STATUS_DISCHARGING 和 BATTERY_STATUS_NOT_CHARGING 之间的区别

    我想知道这两个标志之间的区别 BatteryManager BATTERY STATUS DISCHARGING And BatteryManager BATTERY STATUS NOT CHARGING 我开发了一个使用这两个标志的应用
  • 我应该选择的最低 SDK 版本是多少? (截至2018年11月)

    据我所知 android studio 中默认的最小 SDK 设置是 15 我读到我应该增加它 因为没有多少人 或者可能没有 仍在使用该 android 版本 另外 我计划使用 android studio 中的一些新功能 这些功能仅适用于
  • Android - 多次实例化一个片段?

    我正在创建一个在 ListView 中显示数据的应用程序 数据分为两种类型 热门 收藏夹 我有一个活动和两个片段 片段根据类别显示项目列表 我为此使用了 ListView 然后我有两个fragment layouts 它们在设计上完全相同
  • Spotify 登录错误 INVALID_CLIENT:无效的重定向 URI android

    我正在制作一个包含 Spotify 集成的应用程序 我点击了此链接https developer spotify com technologies spotify android sdk tutorial https developer s
  • 如何在Android网格视图中设置单元格大小?

    我正在尝试为应用程序制作一个带有大图标的网格视图 但我找不到任何有关修改 Android 上网格布局上的单元格大小的教程 有人可以给我一个例子或相关链接吗 Thanks 就像另一个一样适配器视图 http developer android
  • 如何更改 Android 12 启动屏幕中的图标形状?

    我想要矩形形状的启动屏幕图标 而不是 android 12 中的圆形形状 我不相信你可以 如果你看这里的第 3 点 https developer android com about versions 12 features splash
  • BitmapFactory.decodeResource() 忽略 jpg 图像的 inPreferredConfig 选项

    我尝试将jpeg资源图像加载到ARGB 8888格式的位图 BitmapFactory Options opts new BitmapFactory Options opts inPreferredConfig Bitmap Config
  • 如何在 onDraw() 方法中定义与像素无关的高度

    我扩展了 View 来构建自定义小部件 我想用独立的像素单位定义小部件的高度 我认为可以通过将像素密度乘以所需的高度来完成 但我不知道该怎么做 到目前为止我所拥有的 最小化 public class Timeline extends Vie
  • 从 sqlite 和 mysql 加载数据微调器

    我试试这个tutorial http nielpoenya blogspot com 2012 08 tutorial android spinner dari database html加载Spinner from sqlite and
  • 如何从灰度字节缓冲区图像创建位图?

    我正在尝试使用新的 Android 人脸检测移动视觉 API 来处理帧图像 所以我创建了自定义检测器来获取帧并尝试调用 getBitmap 方法 但它为空 所以我访问了帧的灰度数据 有没有办法从它或类似的图像持有者类创建位图 public
  • 如何检查设备上是否安装了文本转语音 (TTS) 的特定语言数据?

    我正在创建一个使用文本转语音的应用程序 我希望用户能够离线使用它 因此我检查设备上是否安装了 TTS 数据 以下是执行此操作的代码 Check tts data is installed Intent checkTTSIntent new

随机推荐

  • Idea2017查看Class字节码文件

    Idea查看字节码文件的原理 1 javap命令的使用 在jdk工具包的bin目录下 xff0c 有一个java可执行文件javap xff0c 该工具可以查看java编译后的class文件 使用命令如下命令进行查看 javap span
  • Idea配置Web项目路径以及使用非默认Tomcat启动

    1 Web项目发布路径配置 1 首先点击Run gt Edit Configurations 2 点击左上角绿色的加号 xff0c 选择Tomcat gt Local 3 点击Deployment 4 点击绿色的小铅笔 5 在此处设置Out
  • emacs下org-mode导出pdf时pdflatex无法找到的问题解决方案

    配置环境 Deepin15 6 Linux emacs25 2 发现的问题 系统没有找到pdflatex命令 xff0c org mode无法导出latex的pdf 解决步骤 安装texlive2018 因为pdflatex是texlive
  • 通过Flask框架封装Tushare获取的日线股票数据

    概要介绍 概要介绍 xff08 TuShare id 282782 xff09 当我们需要进行量化交易分析 xff0c 或者通过代码进行股票的数据计算 xff0c 研究金融时 xff0c 我们需要获取最基本的股票价格 xff0c 开盘价收盘
  • IBM Was 打补丁记录

    0 拷贝解压ifph52925升级包 通过FTP工具 xff0c 把压缩包传到服务器 xff0c unzip d test01 9 0 0 0 ws was ifph52925 zip 1 停掉was 服务 ps ef grep was k
  • CoreText --- 段落样子CTParagraphStyle

    在前面一篇文章中 xff0c 介绍了属性文字的基本使用 xff0c 本章节主要针对文字的段落样式展开演示说明 先定义一段演示文字 xff08 文字中有中 xff0c 英文 xff09 cpp view plain copy NSString
  • 将自己的域名解析跳转到博客主页(GitHub中的gitpage跳转)

    最近突然迷上了博客 xff0c 突然又突发奇想 xff0c 将自己几个月前买的现在限制的域名拿来跳转到自己的csdn博客 经过一番研究 xff0c 总结 把自己的购买的域名 比如我买的circleyuan top 跳转到CSDN博客 只需要
  • Python3.4简单爬虫实现之抓取糗事百科段子

    网上的python教程大都是2 X版本的 xff0c python2 X和python3 X相比较改动比较大 xff0c 好多库的用法不太一样 xff0c 我安装的是3 4 1 xff0c 就用3 4 1实现一下网页内容抓取 首先是库 xf
  • 【C++】类和对象的关系

    概念 xff1a 对象 xff1a 将数据和对数据的操作方法放在一起 xff0c 形成一个相对独立的整体 属性和操作是对象的两大要素 类 xff1a 某一类对象所共有的 本质的属性和类行为 类和对象的关系 类是抽象的 xff0c 对象是具体
  • 美团笔试题_20220409

    前言 笔试一共五道编程题 xff08 四 43 一 xff09 xff0c 一为专项编程题 xff0c 估计不同岗位有题目不一样 xff0c 使用的是赛码网 xff0c 允许跳出界面使用自己的IDE 在此感谢筱羊冰冰提供的部分题目及题解 题
  • Android应用管理一 -- APK包的安装、卸载和优化(PackageManagerService)

    Android的应用管理主要是通过PackageManagerService来完成的 PackageManagerService服务负责各种APK包的安装 卸载 优化和查询 PackageManagerService在启动时会扫描所有的AP
  • Android5.1--多用户模式

    Android中的多用户与Windows的多用户类似 xff0c 可以支持多个用户使用系统 通常 xff0c 第一个在系统中注册的用户将默认成为系统管理员 不同用户的设置各不相同 xff0c 并且不同用户安装的应用及应用数据也不相同 但是系
  • Android--应用安装卸载失败问题分析

    1 应用安装失败 xff1a does not include classes dex 08 04 17 15 23 118W dalvikvm 5253 DexOptZ zip archive 39 data app cloneit 1
  • Android5.1--电源管理之省电模式分析

    一 如何开启5 0省电模式 打开安卓5 0设备的设置选项 xff0c 然后前往电池菜单 xff0c 点击菜单键 xff0c 弹出并选择 节电助手 xff0c 随后点击顶部的开关便可 此外 xff0c 要是用户运行的是原生版安卓 xff0c
  • 如何判断一个未安装的APK是Launcher应用

    网上找的大都是已安装应用的判断方法 xff0c 那么如何判断未安装的apk是否是桌面应用呢 xff1f 直接上代码 xff1a private boolean isLauncherApp String dexPath boolean isH
  • oracle 备份表

    一 PL SQL备份 xff08 1 xff09 打开PL SQL xff08 2 xff09 在Tools下选择Export Tables xff08 3 xff09 在列表中找到想要备份的表 xff0c 右键选择Export Data
  • Android 预置应用

    预置应用主要有4种情况 xff1a 1 如何将带源码的应用预置进系统 xff1f 2 如何将无源码的应用预置 xff08 APK xff09 进系统 xff1f 3 如何预置应用使得用户可以卸载 xff0c 恢复出厂设置时不能恢复 xff1
  • Android广播管理三--广播发送(sendBroadcast)流程分析

    前面我们分析了Android应用程序注册广播接收器的过程 xff0c 接下来它还要等待ActivityManagerService将广播分发过来 ActivityManagerService是如何得到广播并把它分发出去的呢 xff1f 广播
  • 避免后台进程被杀死的几种方法

    Android的几种进程 前台进程 即与用户正在交互的Activity或者Activity用到的Service等 xff0c 如果系统内存不足时前台进程是最后被杀死的 可见进程 可以是处于暂停状态 onPause 的Activity或者绑定
  • Android性能优化 -- Systrace工具

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