写点什么

Android--- 性能优化方案分享,快来收藏

用户头像
Android架构
关注
发布于: 2021 年 11 月 05 日

Debug.startMethodTracing(


"sample-" + logDate);


如果系统在您调用 stopMethodTracing() 之前达到最大缓冲值,则会停止跟踪并向管理中心发送通知。 开始和停止跟踪的函数在您的整个应用流程内均有效。 也就是说,您可以在 Activity 的 onCreate(Bundle)


函数中调用 startMethodTracing(),在 Activity 的 onDestroy() 函数中调用 stopMethodTracing()。

二、查看 .trace 文件

插好桩后,安装应用并运行被检测部分的功能,然后就可以通过 AS 或者 traceview 查看文件了。

使用 AS 查看

在 AS 中点击 View - Tool Windows - Android File Explorer 打开 Android File Explorer :


图片描述


在 /sdcard/Android/data/[YOUR_PACKAGE_NAME]/files 下即可找到生成的 .trace 文件,双击文件即可打开。


将 .trace 文件保存至电脑,直接拖入 AS 窗口,也可直接打开该视图。


图片描述


在打开的视图中,左上方可以选择想要查看的线程。可以查看监控期间指定线程运行了多久、执行了哪些方法、每个方法执行了多久等等。


其中有 4 个名词需要解释一下:


  • **Wall Clock Time:**壁钟时间,表示实际经过的时间,即进入某个方法到退出该方法的时间,不考虑线程是活动还是休眠状态。

  • **Thread time:**线程时间,表示实际经过的时间减去线程没有消耗 CPU 资源(处于休眠)的时间部分。 对于任何给定函数,其线程时间始终少于或等于其壁钟时间。 使用线程时间可以让您更好地了解线程的实际 CPU 使用率中有多少是给定函数消耗的。

  • **Inclusive Time:**方法执行自己代码的时间 + 执行自己 child 方法的时间。

  • **Exclusive Time:**方法执行自己代码的时间。

使用 traceview 查看

要使用 traceview 查看,需要首先将 .trace 文件保存到电脑:


adb pull /sdcard/Android/data/[YOUR_PACKAGE_NAME]/files/sample.trace D:\Documents\sample.trace


打开?Android Device Monitor?。AS3.0 以前的版本,就是 LogCat 所在的窗口,再切换一下 tab 页即可。AS3.0 以后,进入?android-sdk/tools/?路径,运行以下命令:


monitor


图片描述


虽然 Android Device Monitor 的 DDMS 也有 File Explorer ,但是未 root 的手机,查看不到上述路径,因此只能将 .trace 文件保存到电脑查看。


在 Android Device Monitor 中,依次点击?File - Open File?,选择 .trace 文件路径即可打开:


![](http://upload-images.jianshu.io/upload_images/15233854-eebc99


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


81793f007a.PNG?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 "图片描述")


内容与 AS 打开时类似,相差较大的主要是图标部分,没有 AS 的 Call Chart 直观形象。


其中也有 4 个概念:


**Cpu Time:**相当于 AS 中的 Thread time。**Real Time:**相当于 AS 中的 Wall Clock Time。**Inclusive Time:**同 AS 一样。**Exclusive Time:**同 AS 一样。

使用 AS 查看还是使用 traceview 查看

这个就见仁见智了,根据我个人使用的感觉来看,建议使用 AS 查看。原因有二:


AS 更简单。不需要单独打开 ADM,更不需要将 .trace 文件保存到电脑。


AS 的调用图( Call Chart )更加直观,cpu 时间的消耗一目了然。


Call Chart 的水平轴表示函数调用(或调用方)的时间段和时间,并沿垂直轴显示其被调用者。 下图展示了一个调用图表示例,并描绘了给定函数的 self time、children time 以及总时间的概念。


图片描述


最后需要注意一点,跟踪分析过程中,应用的运行速度会减慢。所以,通过 traceview 得到的分析数据并不能精确反应某个方法在实际执行时的绝对时间。关于这一点,在最后的注意事项中再做详细分析。


Google 还提供了基于样本的分析方式,以减少分析对运行时性能的影响。要启用样本分析,需调用 Debug.startMethodTracingSampling() 方法(而非 Debug.startMethodTracing() 方法)。系统会定期收集样本,直至调用 stopMethodTracing() 。

CPU Profiler 使用方法

使用 CPU Profiler 进行函数跟踪比 traceview 更简单。不需要做任何代码上的植入,下面做一个简单的介绍:


首先,通过


View - Tool Windows - Android Profiler 打开 Android Profiler 。手机连接电脑后运行应用,在 Android Profiler 中会看到以下视图:


图片描述


左上角可以选择设备和进程,点击 CPU 区域,即可进入 CPU Profiler 视图:


图片描述


左上角可以选择跟踪模式:


**Sampled:**按默认采样率捕获应用的调用堆栈。该模式的固有问题是,如果应用在一次捕获后进入一个函数并在下一次捕获前退出该函数,则分析器不会记录该函数调用。如果对此类生命周期很短的跟踪函数感兴趣,可以使用“Instrumented”跟踪。


**Instrumented:**以在每个函数调用的开始和结束时记录时间戳。 分析比较时间戳,以生成函数跟踪数据。 需要注意的是,设置与函数关联的开销会影响运行时性能,甚至分析数据,对于生命周期相对较短的函数,这一点更为明显。 此外,如果应用短时间内执行大量函数,则分析器可能会迅速超出它的文件大小限制,且不能再记录更多跟踪数据。


**Edit configurations:**自定义采样率。与 traceview 中的 Debug.startMethodTracingSampling() 类似。


.trace 文件的大小是有限制的。对于给定录制,当分析器到达该限制时,AS 将停止收集新数据(不过,这不会停止记录)。 在执行“Instrumented”跟踪时,这种情况通常会更快发生,因为与“Sampled”跟踪相比,此类跟踪在较短时间里会收集更多数据。


如果你使用的是 Android 8.0(API 26)或更高版本的设备,则对于跟踪数据的文件大小没有限制,此值可忽略。不过,你仍需留意每次记录后设备收集了多少数据,因为 AS 可能难以解析大型跟踪文件。


点击上方的“开始录制”按钮,然后在应用中操作执行被追踪的功能,结束后再点击“停止录制”按钮。CPU Profiler 会自动开始分析并生成数据。


图片描述


以上就是 CPU Profiler 和 traceview 的使用方法。至于如何制定优化方案,就不展开了,并没有完全固定的路子。就我本例的 onRebuild() 方法而言,是针对耗时的 Contact 构造过程做了并行处理,将上百个有序的构造过程平分到 5 个线程中并发执行,然后再按顺序合并数据到一个线程中。最终 onRebuild() 执行速度从 15 秒提升到了 2.5 秒,对我来说已经够用了。

重要注意事项

无论是使用 traceview 还是 CPU Profiler 进行函数跟踪,有一点需要注意:跟踪分析过程中,应用的运行速度会减慢。所以,分析数据并不能精确反应某个方法在实际执行时的绝对时间。下面是我在优化项目中的 onRebuild(boolean) 方法时,记录的 4 组数据,让我们来对比一下:


**实际执行时间:**不启用分析模式,正常运行状态下通过打印日志得到的实际执行时间。**Profiler 统计时间:**使用 CPU Profiler 分析获得的执行时间。**traceview 统计时间:**通过分析 traceview 产生的 .trace 文件,从中获得的执行时间。**traceview 实际时间:**使用 traceview 的情况下,通过打印日志得到的实际执行时间。


为什么针对 traceview 会例举两个时间呢?这是因为测试过程中发现 traceview 自动分析出来的时间比 实际执行时间 不仅没有慢,反而快了很多,疑惑下又在启用 traceview 的情况下通过以下代码测算了一下实际的时间,这个倒是真的比 实际执行时间 慢了。


Debug.startMethodTracing("smssdk_onrebuild");


long curr = System.currentTimeMillis();


onRebuild(true);


Log.d(TAG, "onRebuild lasts: " + (System.currentTimeMillis() - curr));


Debug.stopMethodTracing();

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
Android---性能优化方案分享,快来收藏