前言

讲解的内容大体包含,异步优化,启动优化,卡顿优化,内存优化,ARTHook, 监控耗时盲区,网络,电量,瘦身及APP容灾方案等

性能优化的系统学习方法

330页 PDF Android进阶核心笔记(对应思维导图)

性能优化对应学习思维导图(对应核心笔记)

性能优化学习资料视频(系统,对应导图和笔记)

  • 学习资料
  • 学习视频

既然我们选择了学习Android,那么我们能做的就是不断提升自身的能力,我学每一块都会自己做一张导图,然后对于去找学习资料,视频。这样我学习下来,不仅有程序,有系统,学习效率还高。“精”一个点,就努力做到最好,这就是我对于Android的学习态度。如果也是走上了Android这条路,如果现在的你对性能优化这块感兴趣,但是没有一个明确的学习思路,我给你分享我实战经验总结,帮助你少走一点弯路。

有需要的朋友 私信【进阶】我免费分享给你,当然还是老样子,如果你觉得对你有帮助,希望你能多多,点赞,转发+关注,你们的支持就是我继续的动力。还有其他Android方面想学习的知识,可以留言。最多的我会发文章,并且分享对应的资料给大家。

1.简介

本篇文章是该系列文章中的第一篇,主要介绍的是在一些一线大厂的实际项目中,如果APP发生卡顿是如何进行定位问题的。主要介绍 程序的耗费时间

2.测量时间方式

首先,如果要查看页面加载花费的时间有3种方式

  1. adb命令查看
  2. 手动打点的方式
  3. traceView

3.adb命令

只需要一行命令,就可以查看加载页面的时间。

adb shell am start -W 包名/包名.Activity复制代码

使用后会显示

ThisTime: 代表启动最后一个Activity的耗时

TotalTime: 代表启动所有的Activity的耗时

WaitTime: 代表AMS启动所有的Activity的耗时

注意点:该命令只能是获取配置了的Activity, 其他的无效,因为Android组件中有个 exported 属性,没有intent-filter时exported 属性默认为false,此组件只能由本应用用户访问,配备了intent-filter后此值改变为true,允许外部调用。

缺点: adb命令只能查看配置了的Activity,其他的无法查看,并且也无法精准的查看其方法具体耗费的时间,所以因为其局限性 并不能很好的解决我们问题,我们采用手动打点的方式查看。

4.手动打点

先看代码

public class MyApplication extends Application {    @Override    public void onCreate() {        super.onCreate();        initBugly();        initBaiduMap();        initJPushInterface();        initShareSDK();        ...    }    private void initBugly() throws InterruptedException {        Thread.sleep(1000); // 模拟耗费的时间    }    private void initBaiduMap()  throws InterruptedException {        Thread.sleep(2000); // 模拟耗费的时间    }    private void initJPushInterface() throws InterruptedException {        Thread.sleep(3000); // 模拟耗费的时间    }    private void initShareSDK() throws InterruptedException {        Thread.sleep(500); // 模拟耗费的时间    }}

代码不用我说,项目中很常见,现在的问题是APP启动加载很慢, 那么如何精准的查询到具体耗时的方法?

  long startTime = System.currentTimeMillis();  initBugly();  Log.d("lybj", "initBugly()方法耗时:"+ (System.currentTimeMillis() - startTime));    long startTime = System.currentTimeMillis();  initBaiduMap();  Log.d("lybj", "initBaiduMap()方法耗时:"+ (System.currentTimeMillis() - startTime));  ...

这样可以吗?当然不行,耦合性太大,每一个方法都加,那么测试完了,删除代码也是个体力活,一不小心删错一个,就会造成灾难性的问题,在实际项目中,比如中石油的一些项目,就会采用 AOP 的方式来测量方法的耗费时长。

4.1 AOP

AOP : Aspect Oriented Programming的缩写,意为:面向切面编程

优点:

  1. 针对同一问题的统一处理
  2. 无侵入添加代码

这里我们使用的是Aspectj

4.2 Aspectj 的使用

1.添加依赖

根目录的build.gradle里

buildscript {    ...    dependencies {        ...        classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.0'    }}

app项目的build.gradle及新建的module的build.gradle里添加

apply plugin: 'android-aspectjx'dependencies {    ...    implementation 'org.aspectj:aspectjrt:1.8.+'}

2.创建切面

@Aspectpublic class PerformanceAop {    @Around("call(* com.bj.performance.MyApplication.**(..))")    public void getTime(ProceedingJoinPoint joinPoint){        long startTime = System.currentTimeMillis();        String methodName = joinPoint.getSignature().getName();        try {            joinPoint.proceed();        } catch (Throwable throwable) {            throwable.printStackTrace();        }        Log.d("lybj", methodName + "方法耗时:"+ (System.currentTimeMillis() - startTime));    }}

看,根本无需修改任何工程代码,就可以获取运行时长了,点击运行显示

AspectJ语法参考

缺点: 如果项目比较庞大,上百个方法,总不能全部打掉,然后一个一个的分析到底是哪个地方运行时间过长吧,所以我们需要一个比较直观的工具,一眼就能看到具体哪个方法运行时间过长。

5. traceView的使用

5.1 特点

  1. 图形的形式展示其执行时间调用栈
  2. 信息全面,包含所有进程

5.2 使用方式

Debug.startMethodTracing("文件名");Debug.stopMethodTracing();

在代码中相应位置的地方打入埋点即可, startMethodTracing 有3个构造参数分别是

  1. tracePath:文件名/路径
  2. bufferSize:文件的容量大小
  3. flag:TRACE_COUNT_ALLOCS 只有默认的这一种

代码运行完成后,会在

mnt/sdcard/Android/data/包名/files

生成一个.trace后缀的文件,可以用Profiler添加打开它。

当然也可以使用Profiler的录制功能,但是因为要测量启动时间,点击录制手速并不会那么的精准,所以采用埋点的方式获取trace文件进行分析。

5.3 性能分析

打开文件后为上图所示

5.4 时间模式

上图标签 1 所示:wallclock time 和 cpu time

  1. Wall Clock Time:从进程开始运行到结束,时钟走过的时间,这其中包含了进程在阻塞和等待状态的时间。
  2. Thread Time :就是CPU执行用户指令所用的时间。

注意:如果线程A执行函数b,但是因为函数b加了锁,线程A进入等待状态,那么wallclock time也是要计算时间的,而Thread time则只是计算CPU花费在它身上的时间。

一般根据经验来讲wall duration时间久说明耗时多,然后看Thread time 这个值说明cpu花费在其身上的时间多不多。不多的话基本可以直接异步(因为不抢占CPU)多的话需要合理调度好执行顺序。

5.5 Call Chart

上图标签 2 所示:Call Chart

它的作用就是可以很直观的查看到底是哪里耗时比较久,x轴为调用的时间线,越宽的表示耗时越久,y轴为调用的深度,也就是调用的子方法。父类在最上面,很明显initBottomTab()方法调用是最耗时的。

鼠标悬浮可以查看耗费时间,双击可以跳转到相应代码

  • 橙色:系统方法
  • 蓝色:第三方API(包括java语言的api)
  • 绿色:App自身方法

简易图如下:

5.6 Flame Chart

上图标签 3 所示:Flame Chart 又称之为火焰图

y 轴表示调用栈,每一层都是一个函数。调用栈越深,火焰就越高,顶部就是正在执行的函数,下方都是它的父函数。 x 轴表示抽样数,如果一个函数在 x 轴占据的宽度越宽,就表示它被抽到的次数多,即执行的时间长。注意,x 轴不代表时间,而是所有的调用栈合并后,按字母顺序排列的。

火焰图就是看顶层的哪个函数占据的宽度最大。只要有"平顶"(plateaus),就表示该函数可能存在性能问题。

练习1:

假如火焰图如上图所示,我们需要分析哪个函数吗?

答:最顶层的函数g()占用 CPU 时间最多。d()的宽度最大,但是它直接耗用 CPU 的部分很少。b()和c()没有直接消耗 CPU。因此,如果要调查性能问题,首先应该调查g(),其次是i()。 另外,从图中可知a()有两个分支b()和h(),这表明a()里面可能有一个条件语句,而b()分支消耗的 CPU 大大高于h()。

与Call Chart区别

方法D对B(B1、B2和B3)进行多次调用,其中一些调用B对C(C1和C3)进行调用。如果用Call Chart表示,则为

因为B1、B2和B3共享相同的序列调用者(A→D→B)聚合,如下所示。同样,C1和C3聚合,因为它们共享相同的序列调用者(A→D→B→C)注意不包括C2, 因为它有不同的调用者序列(A→D→C)。

那么如果使用火焰图,则表示:

也就是说,收集相同的调用序列的相同方法被收集并表示为火焰图中的一个较长的栏(而不是将它们显示为多个更短的条)

5.7 Top Down

上图标签 4 所示: Top Down 显示一个函数调用列表,在该列表中展开函数节点会显示函数的被调用方

看上图右边区域:

  • Self:方法调用用于执行自己的代码而不是它的子类的时间量。
  • Children:方法调用花费的时间用于执行其被调用者,而不是其自己的代码
  • Total:方法的Self和Children的时间的总和。这表示应用程序执行方法调用的总时间量

5.8 Bottom Up

上图标签 5 所示: Bottom Up 显示一个函数调用列表,在该列表中展开函数节点将显示函数的调用方。

Bottom Up选项卡对于那些消耗最多(或最少)CPU时间的方法的排序方法很有用。可以检查每个节点,以确定哪些调用者在调用这些方法上花费最多的CPU时间。

  • Self:方法调用用于执行自己的代码而不是它的子类的时间量。
  • Children:方法调用花费的时间用于执行其被调用者,而不是其自己的代码
  • Total:方法的Self和Children的时间的总和。这表示应用程序执行方法调用的总和

简略图如下

缺点: 在项目中用到的,最多的还是Call Chart 和 Top Down, 但是traceView的原理就是抓取所有线程的所有函数里的信息,所以会导致程序变慢, 所以常用的是SysTrace

SysTrace 作者用的不多,有兴趣的朋友可以自行百度,用法和traceView的使用差不多,就不在分析了

android 北斗定位代码_大牛三步教你解决,BAT资深APP性能优化系列-卡顿定位问题,收藏哦相关推荐

  1. 为什么计算机桌面图标不见了,桌面上的图标不见了怎么办(电脑桌面图标突然没了怎么办?简单三步教你解决)...

    使用电脑过程中,我们有时候会发现桌面上的图标不见了,或者我们不小心误删了,这时候我们又急着是用电脑,怎么办呢?在这里网际简单三步教你解决!以win10系统来教大家怎么找回我的桌面电脑图标如下简单3步: ...

  2. Android性能优化 - 消除卡顿

    性能优化系列阅读 Android性能优化 性能优化 - 消除卡顿 性能优化 - 内存优化 性能分析工具 - TraceView Android性能分析工具 消除卡顿 什么是卡顿及卡顿的衡量标准 产生卡 ...

  3. Android App 性能优化系列结语篇

    Android App 性能优化系列结语篇 原文出处:http://gold.xitu.io/post/581f4ad667f3560058a33057 关于Android App的优化, 从第一篇的 ...

  4. Android App性能优化系列

    Android App性能优化系列 关于Android App的优化,从第一篇的计划开始,到内存优化的系列文结束,不知不觉近三个月的时间,写了十五六篇相关的博文,算是对自己的知识的一个系统化,也希望能 ...

  5. android 北斗定位代码_iPhone 11 确认支持北斗导航,真相来了!

    点击 哎咆科技 关注我们 最近"北斗"火了. 因为7月31日,北斗三号全球卫星导航系统正式开通.截止8月7日,微博话题"北斗三号全球卫星导航系统正式开通"已有5 ...

  6. java线程太多卡顿_性能优化之卡顿延迟

    和你一起终身学习,这里是程序员 Android 本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇文章,您将收获以下内容: 1.UI 渲染简介 2.识别延迟 3.Visual insp ...

  7. android 应用性能监控软件,App性能监控工具,卡顿

    (609条消息) android 应用性能监控软件,App性能监控工具_weixin_39940154的博客-CSDN博客 APP性能监测的各种工具 - ClareBaby01 - 博客园 (cnbl ...

  8. 如何解决笔记本电脑无线网络连接图标不见的问题 _ 百度经验 --三步教你完美解决所有情况

    笔记本电脑经常会出现wlan   /无线网络图标不见的情况,,或者下方网络图标直接变成了有线网线连接的图标,点击又找不到wlan连接无线网的图标,重启之后也没有用,但是我们可能电脑正在办公,没办法重启 ...

  9. 三步教你解决Invalid bound statement (not found): com.xxx.dao.xxxDao.selectByxx错误!!!!很简单

    1 问题实质: dao层(又叫mapper接口)跟mapper.xml文件没有映射 2 问题原因: 出现这种映射问题的原因分为低级原因和更低级原因两种 更低级原因: (1)dao层的方法和mapper ...

最新文章

  1. [unreal4入门系列之八] 使用VS编译UE4编辑器并添加物体到场景中
  2. 关于导入项目eclipse出现乱码的问题
  3. 题解 P1876 【开灯】
  4. anaconda安装成功测试_学习笔记120—Win10 成功安装Anaconda 【亲测有效,需注意几点!!!】...
  5. [dp] LeetCode 62. Unique Paths
  6. 现代软件工程 作业 4 个人作业
  7. C/C++程序员如何学习英语
  8. 微信小程序框架探究和解析
  9. Ruby 之父:编程要给程序员带来乐趣
  10. 电脑亮度多少对眼睛好_黄江办公文员学费大概是多少,黄江附近哪个电脑学校比较好一点...
  11. mac 思科 链路聚合_链路聚合定义/Eth-trunk/思科华为配置实例
  12. 计算机病毒note01
  13. 输入一个整数判断它是奇数还是偶数
  14. ImgURL一款简单纯粹的图床程序源码
  15. word中出现“由于文件许可权错误,word无法完成保存操作”的解决办法
  16. c++传输二进制数据
  17. 智能小区安防子系统实现
  18. vmware虚拟机安装 安卓Android x86 8.1
  19. K线类型识别—单K线之阳线
  20. Win7系统下使用CCS 5.2.1 进行软件仿真

热门文章

  1. Delphi 数据类型列表
  2. 移动语义-右值引用-完美转发-万字长文让你一探究竟
  3. 传智C++课程笔记-1
  4. 嵌入式FreeRTOS系统,在中断中调用FreeRTOS系统的API函数
  5. TCP listen() Backlog 参数详解
  6. Hi3516A开发--视频输入和输出接口
  7. Android VNC Server
  8. 【译】Using Machine Learning to Understand the Ethereum Blockchain
  9. Android7.0 PowerManagerService(2) WakeLock的使用及流程
  10. Tensorflow学习笔记——word2vec