Android其他4-Android优化

一、工具

TraceView的使用

工欲善其事必先利其器,TraceView工具是AndroidSDK自带的分析工具,使用该工具我们可以看到我们的app启动过程中cpu执行了那些代码以及函数调用的时间。

1、启动TraceView

在AndroidSDK/tools目录下打开monitor也就是DDMS。然后在设备中选择要做TraceView分析的自己的进程。

2、标记进程

然后点击start Method Profiling 按钮。然后你操作自己的app界面一段时间后电子stop Method Profiling。这个时候就会出现分析报告。
在这里插入图片描述
trace文件
在这里插入图片描述

3、分析

在文件的上半部分你可以看到不同的线程(main主线程和binder线程等等),所占用的时间,颜色越大块说明这段时间占用的越长。

在文件的下半部分区域我们能看到app所执行的每个函数所占用的时间和cpu的比例。你可以点击每个调用的函数和函数下main调用的函数等等去查看。我们一般分析时间比较长的函数,然后查看自己的代码有哪些不合理的地方,还有就是有些函数多次被调用也是可以优化的。

指标说明:
Incl(Inclusive) Cpu Time
方法本身和其调用的所有子方法占用CPU时间.
Excl(Exclusive) Cpu Time
方法本身占用CPU时间.
Incl Real Time
方法(包含子方法)开始到结束用时.
Excl Real Time
方法本身开始到结束用时.
Call + Recursion Calls/Total
方法被调用次数 + 方法被递归调用次数.
Cpu Time/Call
方法调用一次占用CPU时间.
Real Time/Call
方法调用一次实际执行时间.
一般来说, 我们使用Real Time/Call排序来找出耗时多的方法
有必要解释下CPU Time和Real Time:
CPU Time 方法实际执行时间(不包括io等待时间)
Real Time 方法开始结束时间差(包括等待时间)
参考:http://stackoverflow.com/questions/15760447/what-is-the-meaning-of-incl-cpu-time-excl-cpu-time-incl-real-cpu-time-excl-re/17902682#17902682

SysTrace的使用

systrace是google官方的系统性能分析工具,它从全局的角度记录了系统当前的状态,并分析给出警告(Atlerts),开发人员可以根据报告进行优化你的代码。

1、打开

打开方式有两种,当然首先设备要链接adb。
一种是用脚本记录:
在AndroidSDK中的platform-tools/systrace目录下有python脚本。使用如下命令进行记录。

python systrace.py -b 8000 -t 5 -o systrace.html

命令的相关参数
在这里插入图片描述
第二种打开方式是用DDMS打开:
在devices设备中点击如下标签。然后配置一些你需要的参数,相对于有图形界面的操作还是比较好理解。
在这里插入图片描述
在这里插入图片描述

2、操作

然后在你设定的systrace记录的时间范围内操作你的app。这时systrace会记录你当前手机的各种状态。并且在指定的目录下生成trace.html文件。

3、分析

使用浏览器打开trace.html文件。首先我们看到很多的Alerts事件,那么在旁边的状态栏中也记录的所有的Alerts事件。
在这里插入图片描述
在这里插入图片描述
点击Alerts:无论是从列表中还是在途中的小圆点,systrace会给出分析。
在这里插入图片描述
比如这个调度延迟是因为某些线程被设置成了后台线程,导致ui更新延迟,系统建议提高线程的优先级。
在这里插入图片描述
比如这黄色的Alert是说我们的ListView的getView方法效率很低。我们要针对优化一下。
整体分析,systrace是对整个系统的记录,所以如果某个时候我们的ui更新是比较慢,我们有可能怪罪于系统而不是我们本身app的问题,比如说ListView的getView我就是已经优化了,当时有时候记录就是比较慢,我们可以按m键标记这一时刻进行上下对比,查看下cpu或者surface等其他进程有没有干扰。
在这里插入图片描述

5、快捷键

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

AMS命令

在AMS里面记录的一些性能信息,启动时间等等可以参考这个文章
https://blog.csdn.net/coderinchina/article/details/78744448

最快速定位启动时间有没有变化的工具是adb 的命令

adb shell am start -S -W com.example.myapplication/com.example.myapplication.SplashActivity
ThisTime: 315
TotalTime: 315
WaitTime: 354
Complete

也可以用adb shell dumpsys pid/pkg

Applications Memory Usage (in Kilobytes):
Uptime: 107007887 Realtime: 593216524

** MEMINFO in pid 22900**
                   Pss  Private  Private  SwapPss     Heap     Heap     Heap
                 Total    Dirty    Clean    Dirty     Size    Alloc     Free
                ------   ------   ------   ------   ------   ------   ------
  Native Heap    19809    19708        0      785    32896    29719     3176
  Dalvik Heap    18689    18616        0      198    14596     7298     7298
 Dalvik Other     1604     1600        0       16                           
        Stack       48       48        0        0                           
       Ashmem        2        0        0        0                           
      Gfx dev     2816     2816        0        0                           
    Other dev      207        0      204        0                           
     .so mmap    25442      380    18736       69                           
    .jar mmap     5791        0     2624        0                           
    .apk mmap     1758        0     1192        0                           
    .ttf mmap     4446        0     2748        0                           
    .dex mmap     8916     1088     7828        0                           
    .oat mmap     2104        0      420        0                           
    .art mmap     5696     4488        0       92                           
   Other mmap      686      156       76        0                           
   EGL mtrack    25896    25896        0        0                           
    GL mtrack     5244     5244        0        0                           
      Unknown     1813     1752        0       25                           
        TOTAL   132152    81792    33828     1185    47492    37017    10474
 
 App Summary
                       Pss(KB)
                        ------
           Java Heap:    23104
         Native Heap:    19708
                Code:    35016
               Stack:       48
            Graphics:    33956
       Private Other:     3788
              System:    16532
 
               TOTAL:   132152       TOTAL SWAP PSS:     1185
 
 Objects
               Views:       54         ViewRootImpl:        2
         AppContexts:        6           Activities:        1
              Assets:       16        AssetManagers:        0
       Local Binders:       22        Proxy Binders:       40
       Parcel memory:       15         Parcel count:       55
    Death Recipients:        2      OpenSSL Sockets:        3
            WebViews:        0
 
 SQL
         MEMORY_USED:      199
  PAGECACHE_OVERFLOW:       43          MALLOC_SIZE:      117
 

二、启动优化

1、application的优化

尽可能的将第三方库的初始化工作,和一些业务代码延迟到后面初始化,比如ImageLoder的初始化,我们可以换成单例模式,在需要使用的时候初始化。
将一些业务代码,放到单独的线程中优化。这些都市基于不影响业务的情况下的调优。

2、启动页的优化

1.1.解决黑白屏问题

在启动MainActivity前,加载一个SpashActivity。然后加上全屏主题,这个有两种方式。一种是在主题中设置。另外一种是代码中设置

<style name="SplashTheme" parent="AppTheme">
    <item name="android:windowFullscreen">true</item>
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowNoTitle">true</item>
</style>

第二种方式是代码设置

supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                    WindowManager.LayoutParams.FLAG_FULLSCREEN);

1.2.在这个SpashAcivity中可以提前做一些事情

目前很多app是用来做AD的加载。
同时在后台我们可以对我们的view进行提前的加载。可以使用Fragment或者其他的可以方式都可以。
同时我们还可以丢一些线程做一些资源的预加载,等真正的MainAcitivty起来的时候就可以直接使用。

3、View的优化

View 优化其实是需要很多精力的,除了使用viewstub做延迟加载,我们要牢牢记住一个核心观念,就是你写的xml文件无论是层级负载也好还是不复杂也好,你需要用你的经验让你整个layout在绘制的时候尽量一遍绘制完成。
比如使用 Ralectivtylayout androidx的ConstraintLayout,就让系统在绘制view 的时候从上到下基本上扫描一遍就完成了各个子view的定位。而LinearLayout就是写的时候方便,但是系统在绘制的时候,由于你的层级过多,它要反复的确认你的view 的位置导致耗时。

三、系统化优化方法

0.概述

我曾经做过一个整体框架的预加载项目,有空的同学可以尝试一下,当一个最简单的helloword启动的时候,比较耗时的地方在哪里。
我的尝试过的有几个地方。

  • 1、app被点击后的进程fork阶段
  • 2、进程加载类资源阶段对于 classlaoder 执行阶段
  • 3、view的生成和创建

于是我基于以上3点问题,直接做了一个后台app的预加载。加载完成后基本是0ms启动。而这个项目本身带来的商业价值不是很大,但是通过这个过程你能明白,0ms启动到100ms到300ms启动app的耗时再哪里。

1、预加载

在进程起来之前,可以尽可能多的将资源放到内存中
比如:使用PreFork、PreLoade、readhead 、ionice等工具使得文件快速的被进程读取。
参考文章:

  • https://zhuanlan.zhihu.com/p/92497570
  • https://github.com/luckybilly/PreLoader/blob/master/README-zh-CN.md
  • 《Linux IO简单原理》

既然文件的读取影响了启动速度,马上有几个技术基于这一原理开始做了一些其他技术补充。

2、资源重排

dex重排—redex工具可以方便大家使用。
如果自己有能力可以自己进行重排,参考文章,https://juejin.cn/post/6844903710020091917

3、减少app的体积

这个相信大家有很多框架和办法去减少app的体积。
从原理上来讲减少app的体积是可以的增大page页面的命中率的。其中有一种情况收获是比较不错的,就是项目本身用的jar或者aar包很多,但是只是用到其中的一部分。有好多累赘。
但是有另外一种是没什么提升的,可能还会下降。就是类用的已经饱和了。经过某些混淆或者压缩的工具,使得类的链接变多。得不偿失。

4、其他系统化方案:

1、线程
确实业务代码很多的情况下,个人一定要把我好线程的使用。这个是体现程序员的素养的时候,控制好线程的数量。有些业务可以延迟启动的可以放到IdleHandler中。多个业务交互作用的,要程序员对业务非常熟悉,自己去配置线程的优先级。其实进程的优先级一定是服务于业务的,业务流程优化、熟悉业务,并且在关键代码中使用优化手段

2、进程
其实在进程层面考虑基于一个原则,假设除了系统进程所有的资源都分配给你的app,那么你的app启动速度是最快的。
当然这种情况很少的。也是有,比如某些夜深人静的晚上,我拿起手机就点击了某个app。
情况少,当时我们要尽量争取到这个情况。从自己内部来讲,自己启动的时候不要给自己增加麻烦,比如自己启动很多个后台进程。从外部来讲启动过程中减少系统和其他app的交互。比如说去其他app那资源用远程的IPC。
有些时候系统本身会帮助你。在我做项目的时候,我发现桌面的进程的优先级比较高的。好死不死,桌面是长期都在的,更糟糕的是桌面有个几个挂件进程。假设cpu时间是100.
桌面主进程,分30 两个挂件子进程 20 20 你的进程30。你说亏不亏。有的同学说不可能。说实话,在早期的系统分配中,桌面的子进程优先级是比你app进程还高的。但是后面我们有了进程冻结技术,我就建议把桌面的子进程冻结了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

沈万三djh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值