Android卡顿

参考Awesome-Android-Interview

Demo:Advanced

线下调试

Linux命令

说到卡顿,主要都和 CPU 相关。刷了几篇CPU文章,造成卡顿的原因最终都会反映到 CPU 时间上。

CPU 时间分为两种:用户时间和系统时间。用户时间就是执行用户态应用程序代码所消耗的时间;系统时间就是执行内核态系统调用所消耗的时间,包括 I/O、锁、中断以及其他系统调用的时间。

Linux环境下进程的CPU占用率,获取手机cpu方法

E:\zt\project\jitpack\Advanced>adb shell
// 获取 CPU 核心数
heroqltechn:/ $ cat /sys/devices/system/cpu/possible
0-3
// 获取某个 CPU 的频率
heroqltechn:/ $ cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq
1593600

 

Traceview

生成trace日志方法

使用 CPU Profiler 检查 CPU 活动

Traceview 可以用来查看整个过程有哪些函数调用,但是工具本身带来的性能开销过大,有时无法反映真实的情况。比如一个函数本身的耗时是 1 秒,开启 Traceview 后可能会变成 5 秒,而且这些函数的耗时变化并不是成比例放大。

 

Nanoscope

另外介绍一款,Uber 开源的Nanoscope就能达到这个效果。它的实现原理是直接修改 Android 虚拟机源码,在ArtMethod执行入口和执行结束位置增加埋点代码,将所有的信息先写到内存,等到 trace 结束后才统一生成结果文件。

但是它也有不少限制:需要自己刷 ROM,并且当前只支持 Nexus 6P,或者采用其提供的 x86 架构的模拟器。默认只支持主线程采集,其他线程需要代码手动设置。考虑到内存大小的限制,每个线程的内存数组只能支持大约 20 秒左右的时间段。

 

systrace

使用

利用了 Linux 的ftrace调试工具,相当于在系统各个关键位置都添加了一些性能探针,也就是在代码里加了一些性能监控的埋点。

systrace 跟踪系统的 I/O 操作、CPU 负载、Surface 渲染、GC 等事件。

systrace 工具有选择性或者采用抽样的方式观察某些函数调用过程,只能监控特定系统调用的耗时情况,而且性能开销非常低。但是它不支持应用程序代码的耗时分析,所以在使用时有一些局限性。

我们可以通过编译时给每个函数插桩的方式来实现,也就是在重要函数的入口和出口分别增加Trace.beginSection和Trace.endSection。

 

注意

AS在3.0之后删除之前的了 Tools目录下的Android菜单,这样就导致以前通过Tools——>Android——>DeviceMonitor打开DDMS的方式行不通啦

最后根据Google 文档自己鼓捣打开DDMS,在此记录一下:

1.先找到配置的SDK路径,我的是E:\android-sdk\sdk;

2.在SDK的android路径tools下monitor.bat 的批处理文件;

3.点击monitor.bat这个批处理文件,在屏幕上会打开一个类似CMD的命令行中输入板,然后迅速自动关闭

4.坐等1到3秒就会打开DDMS;

 

Simpleperf

分析 Native 函数的调用。

 

如果需要分析 Native 代码的耗时,可以选择 Simpleperf;如果想分析系统调用,可以选择 systrace;如果想分析整个程序执行流程的耗时,可以选择 Traceview 或者插桩版本的 systrace。

 

Profiler

Android Studio 3.2 的 Profiler 中直接集成了几种性能分析工具,其中:Sample Java Methods 的功能类似于 Traceview 的 sample 类型。Trace Java Methods 的功能类似于 Traceview 的 instrument 类型。Trace System Calls 的功能类似于 systrace。SampleNative (API Level 26+) 的功能类似于 Simpleperf。

 

线上监控

消息队列

通过替换 Looper 的 Printer 实现。

            final Printer logging = me.mLogging;
            if (logging != null) {
                logging.println(">>>>> Dispatching to " + msg.target + " " +
                        msg.callback + ": " + msg.what);
            }

AndroidPerformanceMonitor

也是BlockCanary原理,中文文档

通过一个监控线程,每隔一段时间向主线程消息队列的头部插入一条空消息,然后监测空消息是否被消费。

 

插桩

使用Hook 技术。

参考demo中的CartonActivity页面

            @TimeSpend("btnTime")
            @Override
            public void onClick(View v) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

输出日志
com.example.advanced E/TimeSpendAspect: 功能:btnTime,类的onClick方法执行了,用时1000 ms

Profilo

Facebook 开源了一个叫Profilo的库,集成 atrace 功能,快速获取 Java 堆栈。

demo项目地址

Profilo 的实现非常精妙,它实现类似 Native 崩溃捕捉的方式快速获取 Java 堆栈,通过间隔发送 SIGPROF 信号,整个过程如下图所示。

 

### 解决 Android 系统或应用程序卡顿问题 #### 一、原因分析 Android系统或应用卡顿的原因多种多样,主要包括耗时操作阻塞UI线程、布局和绘制复杂度高以及内存不足等问题[^1]。具体来说: - **UI 绘制**:复杂的视图层次结构可能导致频繁的重绘和测量过程,从而拖慢渲染速度。 - **应用启动**:初始化过程中加载过多资源或者执行大量计算任务会影响启动效率。 - **页面跳转**:如果每次切换活动都需要重新创建对象,则可能会造成短暂延迟。 - **事件响应**:当用户交互触发的操作未能及时完成时也会让用户感觉到迟缓。 #### 二、解决方案概述 为了有效缓解上述各类情形下的卡顿现象,可以从以下几个方面入手改进程序设计与实现方式: ##### (一)采用异步机制减轻主线程负担 对于那些不可避免地需要长时间运行的任务(如网络请求),应当将其移至后台线程中执行,并利用`AsyncTask`, `HandlerThread` 或者更高级别的抽象层——RxJava 来简化并发编程模型。这样不仅可以防止因等待 I/O 完成而造成的界面冻结,还能更好地管理多线程间的通信协调工作。 ```java new Thread(new Runnable() { @Override public void run() { // 执行耗时操作... handler.post(new Runnable(){ @Override public void run(){ // 更新 UI ... } }); } }).start(); ``` ##### (二)优化视图构建流程减少重复劳动 针对由繁杂控件组合引发的问题,一方面要精简不必要的嵌套层级;另一方面则可通过预加载部分数据提前准备好待展示的内容片段,在实际显示前仅需简单拼接即可呈现给最终使用者观看。此外,合理设置属性值也能起到一定辅助作用,例如启用硬件加速功能可显著加快图形变换的速度[^2]。 ##### (三)控制资源占用量维持稳定状态 考虑到移动终端本身的局限性,务必时刻关注当前可用空间大小并适时释放不再使用的组件实例及其关联的数据集。特别是图片素材往往占据较大体积,因此建议引入第三方库 Glide/Fresco 实现高效的图像压缩传输方案,同时配合 LRU 缓存策略进一步降低磁盘读写频率[^3]。 ##### (四)借助调试工具精准定位根源所在 除了依靠直觉猜测外,还可以运用官方提供的 Traceview 工具深入剖析整个生命周期内的各项指标表现情况,从中筛选出异常突出的部分作为重点攻关方向。该软件能够直观反映出各环节所耗费的具体毫秒数连同其内部调用链路详情,有助于快速锁定可疑代码段落以便后续针对性调整优化措施[^5]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值