深入探索Android卡顿优化(上)cpu

[Linux C++] 分析线程的CPU占用率模块 - 空水 - 博客园 (cnblogs.com)

Android 性能测试 - CPU - 简书 (jianshu.com)

Android性能优化之CPU Profiler - 简书 (jianshu.com)

(617条消息) Android:Profiler_Android进阶之路的博客-CSDN博客

(617条消息) anr用户无响应问题的解决_融化的雪的博客-CSDN博客

(597条消息) 深入探索Android卡顿优化(上)_android 进程占用cpu时间过长_JsonChao的博客-CSDN博客

上边介绍很多方法,就看这个就可以 AndroidPerformanceMonitor

那么卡顿问题到底难在哪里呢?

1、卡顿产生的原因是错综复杂的,它涉及到代码、内存、绘制、IO、CPU等等。

2、线上的卡顿问题在线下是很难复现的,因为它与当时的场景是强相关的,比如说线上用户的磁盘IO空间不足了,它影响了磁盘IO的写入性能,所以导致卡顿。针对这种问题,我们最好在发现卡顿的时候尽量地去记录用户当时发生卡顿时的具体的场景信息。

2、卡顿分析方法之使用shell命令分析CPU耗时

尽管造成卡顿的原因有很多种,不过最终都会反映到CPU时间上。

CPU时间包含用户时间和系统时间。

用户时间:执行用户态应用程序代码所消耗的时间。

系统时间:执行内核态系统调用所消耗的时间,包括I/O、锁、中断和其它系统调用所消耗的时间。

CPU的问题大致可以分为以下三类:

1、CPU资源冗余使用

算法效率太低:明明可以遍历一次的却需要去遍历两次,主要出现在查找、排序、删除等环节。

没有使用cache:明明解码过一次的图片还去重复解码。

计算时使用的基本类型不对:明明使用int就足够,却要使用long,这会导致CPU的运算压力多出4倍。

2、CPU资源争抢

抢主线程的CPU资源:这是最常见的问题,并且在Android 6.0版本之前没有renderthread的时候,主线程的繁忙程度就决定了是否会引发用户的卡顿问题。

抢音视频的CPU资源:音视频编解码本身会消耗大量的CPU资源,并且其对于解码的速度是有硬性要求的,如果达不到就可能产生播放流畅度的问题。我们可以采取两种方式去优化:1、尽量排除非核心业务的消耗。2、优化自身的性能消耗,把CPU负载转化为GPU负载,如使用renderscript来处理视频中的影像信息。

大家平等,互相抢:比如在自定义的相册中,我开了20个线程做图片解码,那就是互相抢CPU了,结果就是会导致图片的显示速度非常慢。这简直就是三个和尚没水喝的典型案例。因此,在自定义线程池的时候我们需要按照系统核心数去控制线程数。

3、CPU资源利用率低

对于启动、界面切换、音视频编解码这些场景,为了保证其速度,我们需要去好好利用CPU。而导致无法充分利用CPU的因素,不仅有磁盘和网络I/O,还有锁操作、sleep等等。对于锁的优化,通常是尽可能地缩减锁的范围。

1、了解CPU 性能

3、StrictMode

StrictMode是Android 2.3引入的一个工具类,它被称为严苛模式,是Android提供的一种运行时检测机制,可以用来帮助开发人员用来检测代码中一些不规范的问题。对于我们的项目当中,可能会成千上万行代码,如果我们用肉眼Review,这样不仅效率非常低效,而且比较容易出问题。使用StrictMode之后,系统会自动检测出来在主线程中的一些异常情况,并按照我们的配置给出相应的反应。

StrictMode这个工具是非常强大的,但是我们可能因为对它不熟悉而忽略掉它。StrictMode主要用来检测两大问题:

1、线程策略

线程策略的检测内容,是一些自定义的耗时调用、磁盘读取操作以及网络请求等。

2、虚拟机策略

4、Profilo

Profilo是一个用于收集应用程序生产版本的性能跟踪的Android库。

对于Profilo来说,它集成了atrace功能,ftrace 所有的性能埋点数据都会通过 trace_marker 文件写入到内核缓冲区,Profilo 使用了 PLT Hook 拦截了写入操作,以选择部分关心的事件去做特定的分析。这样所有的 systrace 的探针我们都可以拿到,例如四大组件生命周期、锁等待时间、类校验、GC 时间等等。不过大部分的 atrace 事件都比较笼统,从事件“B|pid|activityStart”,我们无法明确知道该事件具体是由哪个 Activity 来创建的。

此外,使用Profilo还能够快速获取Java堆栈。由于获取堆栈需要暂停主线程的运行,所以profilo通过间隔发送 SIGPROF 信号这样一种类似 Native 崩溃捕捉的方式去快速获取 Java 堆栈。

Profilo能够低耗时地快速获取Java堆栈的具体实现原理为当Signal Handler 捕获到信号后,它就会获取到当前正在执行的 Thread,通过 Thread 对象就可以拿到当前线程的 ManagedStack,ManagedStack 是一个单链表,它保存了当前的 ShadowFrame 或者 QuickFrame 栈指针,先依次遍历 ManagedStack 链表,然后遍历其内部的 ShadowFrame 或者 QuickFrame 还原一个可读的调用栈,从而 unwind 出当前的 Java 堆栈。关于ManagedStack与ShadowFrame、QuickFrame三者的关系如下图所示:

Profilo通过这种方式,就可以实现线程同步运行的同时,我们还可以去帮它做检查,并且耗时基本可以忽略不计。但是目前 Profilo 快速获取堆栈的功能不支持 Android 8.0 和 Android 9.0,并且它内部使用了Hook等大量的黑科技手段,鉴于稳定性问题,建议采取抽样部分用户的方式来开启该功能。

Profilo项目地址

二、自动化卡顿检测方案及优化

1、为什么需要自动化卡顿检测方案?

主要有一下两点原因:

1、Cpu Profiler、Systrace等系统工具仅适合线下针对性分析。

2、线上及测试环境需要自动化的卡顿检方案来定位卡顿,同时,更重要的是,它能记录卡顿发生时的场景。

2、卡顿检测方案原理

它的原理源于Android的消息处理机制,一个线程不管有多少Handler,它只会有一个Looper存在,主线程执行的任何代码都会通过Looper.loop()方法执行。而在Looper函数中,它有一个mLogging对象,这个对象在每个message处理前后都会被调用。主线程发生了卡顿,那一定是在dispatchMessage()方法中执行了耗时操作。那么,我们就可以通过这个mLogging对象对dispatchMessage()进行监控。

卡顿检测方案的具体实现步骤

首先,我们看下Looper用于执行消息循环的loop()方法,关键代码如下所示:

3、AndroidPerformanceMonitor

它是一个非侵入式的性能监控组件,可以通过通知的形式弹出卡顿信息。它的原理就是我们刚刚讲述到的卡顿监控的实现原理。

接下我们通过一个简单的示例来讲解一下它的使用。

首先,我们需要在moudle的build.gradle下配置它的依赖,如下所示:

然后,我们运行项目,打开App,即可看到类似LeakCanary界面那样的卡顿信息堆栈。

除了发生卡顿时BlockCanary提供的图形界面可供开发和测试人员直接查看卡顿原因之外。其最大的作用还是在线上环境或者自动化monkey测试的环节进行大范围的log采集与分析,对于分析的纬度,可以从以下两个纬度来进行:

卡顿时间。

根据同堆栈出现的卡顿次数来进行排序和归类。

BlockCanary的优势如下

非侵入式。

方便精准,能够定位到代码的某一行代码。

那么这种自动检测卡顿的方案有什么问题吗?

在卡顿的周期之内,应用确实发生了卡顿,但是获取到的卡顿信息可能会不准确,和我们的OOM一样,也就是最后的堆栈信息仅仅只是一个表象,并不是真正发生问题时的一个堆栈。下面,我们先看下如下的一个示意图:

根据图中,可以梳理出优化后的具体实现步骤为:

1、首先,我们会通过startMonitor方法对这个过程进行监控。

2、接着,我们就开始高频采集堆栈信息。如果发生了卡顿,我们就会调用endMonitor方法。

3、然后,将之前我们采集的多个堆栈信息记录到文件中。

4、最后,在合适的时机上报给我们的服务器。

通过上述的优化,我们就可以知道在整个卡顿周期之内,究竟是哪些方法在执行,哪些方法比较耗时。

但是这种海量卡顿堆栈的处理又存在着另一个问题,那就是高频卡顿上报量太大,服务器压力较大,这里我们来分析下如何减少服务端对堆栈信息的处理量。

在出现卡顿的情况下,我们采集到了多个堆栈,大概率的情况下,可能会存在多个重复的堆栈,而这个重复的堆栈信息才是我们应该关注的地方。我们可以对一个卡顿下的堆栈进行能hash排重,找出重复的堆栈。这样,服务器需要处理的数据量就会大大减少,同时也过滤出了我们需要重点关注的对象。对于开发人员来说,就能更快地找到卡顿的原因。

4、小结

在本节中,我们学习了自动化卡顿检测的原理,然后,我们使用这种方案进行了实战,最后,我还介绍了这种方案的问题和它的优化思路。

三、总结

在本篇文章中,我们主要对卡顿优化分析方法与工具

、自动化卡顿检测方案及优化相关的知识进行了全面且深入地讲解,这里再简单总结一下本篇文章涉及的两大主题:

1、卡顿优化分析方法与工具:背景介绍、卡顿分析方法之使用shell命令分析CPU耗时、卡顿优化工具。

2、自动化卡顿检测方案及优化:卡顿检测方案原理、AndroidPerformanceMonitor实战及其优化。

下篇,笔者将带领大家更加深入地去学习卡顿优化的相关知识,敬请期待~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值