深入解析:Android卡顿检测及优化项目实战经验总结,任君白嫖

3.主线程调度不到 , 处于 Runnable 状态

当线程为 Runnable 状态的时候 , 调度器如果迟迟不能对齐进行调度 , 那么就会产生长时间的 Runnable 线程状态 , 导致错过 Vsync 而产生流畅性问题。

4、System 锁

system_server 的 AMS 锁和 WMS 锁 , 在系统异常的情况下 , 会变得非常严重 , 如下图所示 , 许多系统的关键任务都被阻塞 , 等待锁的释放 , 这时候如果有 App 发来的 Binder 请求带锁 , 那么也会进入等待状态 , 这时候 App 就会产生性能问题 ; 如果此时做 Window 动画 , 那么 system_server 的这些锁也会导致窗口动画卡顿

5、Layer过多导致 SurfaceFlinger Layer Compute 耗时

Android P 修改了 Layer 的计算方法 , 把这部分放到了 SurfaceFlinger 主线程去执行, 如果后台 Layer 过多, 就会导致 SurfaceFlinger 在执行 rebuildLayerStacks 的时候耗时 , 导致 SurfaceFlinger 主线程执行时间过长。

从应用层来看以下会导致卡顿:

1、主线程执行时间长 主线程执行 Input \ Animation \ Measure \ Layout \ Draw \ decodeBitmap 等操作超时都会导致卡顿 。

  • 1、Measure \ Layout 耗时\超时

  • 2、draw耗时

  • 3、Animation回调耗时

  • 4、View 初始化耗时

  • 5、List Item 初始化耗时

  • 6、主线程操作数据库

2、主线程 Binder 耗时

Activity resume 的时候, 与 AMS 通信要持有 AMS 锁, 这时候如果碰到后台比较繁忙的时候, 等锁操作就会比较耗时, 导致部分场景因为这个卡顿, 比如多任务手势操作。

3、WebView 性能不足

应用里面涉及到 WebView 的时候, 如果页面比较复杂, WebView 的性能就会比较差, 从而造成卡顿

4、帧率与刷新率不匹配

如果屏幕帧率和系统的 fps 不相符 , 那么有可能会导致画面不是那么顺畅. 比如使用 90 Hz 的屏幕搭配 60 fps 的动画。

卡顿检测

====

卡顿检测可以使用以下多种方法同时进行:

1、使用dumpsys gfxinfo

2、使用Systrace获取相关信息

3、使用LayoutInspect 检测布局层次

4、使用BlockCanary

5、利用Choreographer。

6、使用严格模式(StrictMode )。

1、使用dumpsys gfxinfo


在开发过程中发现有卡顿发生时可以使用下面的命令来获取卡顿相关的信息:

adb shell dumpsys gfxinfo [PACKAGE_NAME]

输入这个命令后可能会打印下面的信息:

Applications Graphics Acceleration Info:

Uptime: 102809662 Realtime: 196891968

** Graphics info for pid 31148 [com.android.settings] **

Stats since: 524615985046231ns

Total frames rendered: 8325

Janky frames: 729 (8.76%)

90th percentile: 13ms

95th percentile: 20ms

99th percentile: 73ms

Number Missed Vsync: 294

Number High input latency: 47

Number Slow UI thread: 502

Number Slow bitmap uploads: 44

Number Slow issue draw commands: 135

上面参数说明:

Graphics info for pid 31148 [com.android.settings]: 表明当前dump的为设置界面的帧信息,pid为31148 Total frames rendered: 8325 本次dump搜集了8325帧的信息

Janky frames :729 (8.76%)出现卡顿的帧数有729帧,占8.76%

Number Missed Vsync: 294 垂直同步失败的帧

Number Slow UI thread: 502 因UI线程上的工作导致超时的帧数

Number Slow bitmap uploads: 44 因bitmap的加载耗时的帧数

Number Slow issue draw commands: 135 因绘制导致耗时的帧数

2、使用systrace


上面使用的dumpsys是能发现问题或者判断问题的严重性,但无法定位真正的原因。如果要定位原因,应当配合systrace工具使用。

systrace使用

Systrace可以帮助分析应用是如何设备上运行起来的,它将系统和应用程序线程集中在一个共同的时间轴上,分析systrace的第一步需要在程序运行的时间段中抓取trace log,在抓取到的trace文件中,包含了这段时间中想要的关键信息,交互情况。

图1显示的是当一个app在滑动时出现了卡顿的现象,默认的界面下,横轴是时间,纵向为trace event,trace event 先按进程分组,然后再按线程分组.从上到下的信息分别为Kernel,SurfaceFlinger,应用包名。通过配置trace的分类,可以根据配置情况记录每个应用程序的所有线程信息以及trace event的层次结构信息。

Android studio中使用systrace

1、在android设备的 设置 – 开发者选项 – 监控 – 开启traces。 2、选择要追中的类别,并且点击确定。

完成以上配置后,开始抓trace文件

$ python systrace.py --cpu-freq --cpu-load --time=10 -o mytracefile.html

分析trace文件 抓到trace.html文件后,通过web浏览器打开

检查Frames 每个应用程序都有一排代表渲染帧的圆圈,通常为绿色,如果绘制的时间超过16.6毫秒则显示黄色或红色。通过“W”键查看帧。

trace应用程序代码 在framework中的trace marker并没有覆盖到所有代码,因此有些时候需要自己去定义trace marker。在Android4.3之后,可以通过Trace类在代码中添加标记,这样将能够看到在指定时间内应用的线程在做哪些工作,当然,trace 的begin和end操作也会增加一些额外的开销,但都只有几微秒左右。 通过下面的例子来说明Trace类的 用法。

public class MyAdapter extends RecyclerView.Adapter {

@Override

public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

Trace.beginSection(“MyAdapter.onCreateViewHolder”);

MyViewHolder myViewHolder;

try {

myViewHolder = MyViewHolder.newInstance(parent);

} finally {

Trace.endSection();

}

return myViewHolder;

}

@Override

public void onBindViewHolder(MyViewHolder holder, int position) {

Trace.beginSection(“MyAdapter.onBindViewHolder”);

try {

try {

Trace.beginSection(“MyAdapter.queryDatabase”);

RowItem rowItem = queryDatabase(position);

mDataset.add(rowItem);

} finally {

Trace.endSection();

}

holder.bind(mDataset.get(position));

} finally {

Trace.endSection();

}

}

}

3 、使用BlockCanary


BlockCanary是国内开发者MarkZhai开发的一套性能监控组件,它对主线程操作进行了完全透明的监控,并能输出有效的信息,帮助开发分析、定位到问题所在,迅速优化应用。 其特点有:

1、非侵入式,简单的两行就打开监控,不需要到处打点,破坏代码优雅性。

2、精准,输出的信息可以帮助定位到问题所在(精确到行),不需要像Logcat一样,慢慢去找。

3、目前包括了核心监控输出文件,以及UI显示卡顿信息功能

BlockCanary基本原理

android应用程序只有一个主线程ActivityThread,这个主线程会创建一个Looper(Looper.prepare),而Looper又会关联一个MessageQueue,主线程Looper会在应用的生命周期内不断轮询(Looper.loop),从MessageQueue取出Message 更新UI。

public static void loop() {

for (;😉 {

// This must be in a local variable, in case a UI event sets the logger

Printer logging = me.mLogging;

if (logging != null) {

logging.println(">>>>> Dispatching to " + msg.target + " " +

msg.callback + ": " + msg.what);

}

msg.target.dispatchMessage(msg);

if (logging != null) {

logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);

}

}

}

复制代码

BlockCanary主要是检测msg.target.dispatchMessage(msg);之前的>>>>> Dispatching to 和之后的<<<<< Finished to的间隔时间。 应用发生卡顿,一定是在dispatchMessage中执行了耗时操作。通过给主线程的Looper设置一个Printer,打点统计dispatchMessage方法执行的时间,如果超出阀值,表示发生卡顿,则dump出各种信息,提供开发者分析性能瓶颈。

4、使用Choreographer


Android 主线程运行的本质,其实就是 Message 的处理过程,我们的各种操作,包括每一帧的渲染操作 ,都是通过 Message 的形式发给主线程的 MessageQueue ,MessageQueue 处理完消息继续等下一个消息。

Choreographer 的引入,主要是配合 Vsync ,给上层 App 的渲染提供一个稳定的 Message 处理的时机,也就是 Vsync 到来的时候 ,系统通过对 Vsync 信号周期的调整,来控制每一帧绘制操作的时机. 目前大部分手机都是 60Hz 的刷新率,也就是 16.6ms 刷新一次,系统为了配合屏幕的刷新频率,将 Vsync 的周期也设置为 16.6 ms,每个 16.6 ms , Vsync 信号唤醒 Choreographer 来做 App 的绘制操作 ,这就是引入 Choreographer 的主要作用。

Choreographer 两个主要作用

1、承上:负责接收和处理 App 的各种更新消息和回调,等到 Vsync 到来的时候统一处理。比如集中处理 Input(主要是 Input 事件的处理) 、Animation(动画相关)、Traversal(包括 measure、layout、draw 等操作) ,判断卡顿掉帧情况,记录 CallBack 耗时等。

2、启下:负责请求和接收 Vsync 信号。接收 Vsync 事件回调(通过 FrameDisplayEventReceiver.onVsync );请求 Vsync(FrameDisplayEventReceiver.scheduleVsync) .

使用Choreographer 计算帧率

Choreographer 处理绘制的逻辑核心在 Choreographer.doFrame 函数中,从下图可以看到,FrameDisplayEventReceiver.onVsync post 了自己,其 run 方法直接调用了 doFrame 开始一帧的逻辑处理:

Choreographer周期性的在UI重绘时候触发,在代码中记录上一次和下一次绘制的时间间隔,如果超过16ms,就意味着一次UI线程重绘的“丢帧”。丢帧的数量为间隔时间除以16,如果超过3,就开始有卡顿的感知。 使用Choreographer检测帧的代码如下:

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

最后

今天关于面试的分享就到这里,还是那句话,有些东西你不仅要懂,而且要能够很好地表达出来,能够让面试官认可你的理解,例如Handler机制,这个是面试必问之题。有些晦涩的点,或许它只活在面试当中,实际工作当中你压根不会用到它,但是你要知道它是什么东西。

最后在这里小编分享一份自己收录整理上述技术体系图相关的几十套腾讯、头条、阿里、美团等公司19年的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。

还有 高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

【Android核心高级技术PDF文档,BAT大厂面试真题解析】

【算法合集】

【延伸Android必备知识点】

【Android部分高级架构视频学习资源】

**Android精讲视频领取学习后更加是如虎添翼!**进军BATJ大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水,赶快领取吧!

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

T大厂面试真题解析】**

[外链图片转存中…(img-0NZ6XJhY-1713680534140)]

【算法合集】

[外链图片转存中…(img-ISpCqKwu-1713680534141)]

【延伸Android必备知识点】

[外链图片转存中…(img-NLEkyGif-1713680534142)]

【Android部分高级架构视频学习资源】

**Android精讲视频领取学习后更加是如虎添翼!**进军BATJ大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水,赶快领取吧!

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 26
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值