Systrace的使用总结

目的:

 为了提高apk的性能,使得apk在任何情况下,包括:cpu使用频繁,内存较少,用户重度使用手机(即用户使用一年后的情况,包含大量的图片,音乐和应用数据)都能够快速启动。

 慢启动标准:1000ms。

 一般启动标准:对标友商的启动时间。(一般为100ms)

统计方法:

 1、monkey测试平台自动统计启动最久的时长和超时次数。

 2、在event log中,搜索“am_activity_launch_time”找出所有的启动时长,再根据包名进一步筛选。

 3、在main log中,搜索“Displayed 包名/Activity类”,也可以找出所有的启动记录

其中:测试部使用的是第一种方法。自己排查复现时,只能使用第二种或者第三种方法。

问题复现:

 一般启动分析:

方法1:

  在Android Device Monitor,选中设备,点击Capture System

配置trace,点击OK。然后操作手机,进行启动。

方法2:

 仅限努比亚手机。在onResume延迟1s执行reflectDumpSysTrace()方法,即可在手机内存dump systrace文件。

然后分析执行时间较久的原因。

方法:

public static void reflectDumpSysTrace(){

ActivityManager activityManager =(ActivityManager)MyApplication.getInstance().getSystemService(Context.ACTIVITY_SERVICE);

    try {

        Method 

method = activityManager.getClass().getDeclaredMethod("dumpSystrace");

method.setAccessible(true);

method.invoke(activityManager);

    } catch (Exception e){

    e.printStackTrace();

    }

}

慢启动分析:

预制步骤:导入重度用户数据,执行整机monkey(50w次)。

方法1:

 在onCreate记录时间,然后在onResume记录时间,比较时间差。大于350ms时,使用上述方法输出systrace。 (onResume会执行多次,应该只计算第一次的执行时间。)

方法2:

  使用设定在local.prop的方式或"adb shell setprop"命令设置以下两个系统属性

"debug.nubia.systrace_launch":activity的启动时间阈值,超过该值则dumpsystrace(单位:ms)

"debug.nubia.systrace_launch_pkg":应用包名(默认为空值),可设置多个,使用":"分隔;也可设置为"*",表示全部应用

工具使用

使用浏览器打开systrace。

操作:

          m:选中当前片段/取消选择

快捷键

问题排查

定位到应用:

  一直下拉,直至找到包名。有时候包名不显示,只能根据pid查找。(无快捷方法)

主要查看UI Thread.

一直到第一帧绘制出来的时间就是启动时间(绿色的F)

启动时间

查找执行时间:用鼠标选择从activity启动开始到第一帧绘制完成的时间片段。

结果如下:

启动耗时详情

总时间7s多,可以看出大部分时间都在休眠。(Running的时间就是cpu执行的时间)

查找休眠长的片段(空白的片段),然后右键查下一个片段(Runable)。查出是那个tid(wake from)阻塞了。然后在右上角查找tid,找出tid是什么。

如果是system service,一般和应用无关。

休眠原因查看:

休眠原因

如果所示:要查找3138(右上角有搜索框)

休眠阻塞原因

结果是一个system service。一般和应用无关,待进一步分析。

详情查看

在debug版本中

adb shell setprop debug.nubia.systrace_more 1

可以打出所有的系统方法。包括是那个方法导致休眠了。

耗时方法详情

可以看出虽然注册广播所需时间只需要.0643ms,但是在系统繁忙的时候,会导致放大上千倍。需要放在异步线程。但是这个广播不是应用控制的

跳帧分析

跳帧:Android中,有UI更新时,16ms会绘制一帧。跳帧就会给用户造成直观的卡顿现象。启动时间计算也是要第一帧显示完成。

定位:红色的F表示绘制失败

分析:

跳帧图

1、点击红色的F

2、查看警告,站看详情。

3、按照时间顺序,逐个分析,

比如图中的mesure took

212.60ms就是重点分析对象。

4、点击measure方法,定位到具体的方法。

5、按“M”选择当前时间段,通过左右移动和放大查看方法详情。

6、查看耗时原因。


耗时详情分析

名称解释:

Wall Duration    持续时间

CPU Duration     cpu耗时

Self Time            自身方法耗时(不包含其调用方法)

CPU Self Time    自身方法cpu执行时间

案例总结

在该例子中,onMeasue是由于输入法弹窗重新布局触发的。

耗时原因主要是cpu阻塞和嵌套多层导致的。

排查记录:

1、页面更新UI的大量操作。信息需要异步读取,但是读取完成后,更新UI多,也是耗时的,会导致第一帧无法绘制成功。(采用Idle机制延迟加载)

2、标题栏延迟加载,只有设置标题的时候才执行onDraw方法。

3、输入法弹出时重新布局,采用Idle延迟加载

4、除了更新布局外,其他统一由线程池执行,包括:广播,sp,任何跨进程操作。

5、ActionBar,一般情况下需要耗时18ms。优化后采用自定义view,只需要4ms。

6、对比新旧数据,相同的数据不更新。

7、界面嵌套减少,一般要小于三层。

8、对于需要多个组合与嵌套实现的布局,最好的优化方法就是自定义View,只需要一次绘制。(所有的View都是继承View,结合canvas绘制出来的)

9、避免使用AppCompatActivity,这个一定会绘制ActionBar,只能隐藏,但是经过了绘制,再隐藏。耗时,无意义

总结

在掌握性能优化方法的同时,也要学习排查性能问题的方法。就是说,掌握了性能方法,并不能完全避免各种各样的性能问题,只有经过测试,排查,才能把性能问题减少到最低。   

   性能优化原则:

最小嵌套,

最少组合,

尽量异步,

重复利用,

更新延迟加载,

更新局部加载。

话外:使用一个“activity+多个Fragment“代替”多个activity” ,可以极大避免慢启动问题。

你可能感兴趣的:(Systrace的使用总结)