Android 卡顿分析

卡顿

大多数用户感知到的卡顿等性能问题的最主要根源都是因为渲染性能。Android系统每隔大概16.6ms发出VSYNC信号,触发对UI进行渲染,如果每次渲染都成功,这样就能够达到流畅的画面所需要的60fps,为了能够实现60fps,这意味着程序的大多数操作都必须在16ms内完成。

卡顿的原因

如果某个操作花费时间超过16ms,系统在得到VSYNC信号的时候就无法进行正常渲染,这样就发生了丢帧现象。那么用户在32ms内看到的会是同一帧画面。

有很多原因可以导致丢帧,一般主线程过多的UI绘制、显示的Bitmap过大、大量的IO操作、内存抖动、WebView内容复杂、Webview与主线程交互(jsbridge方案)或是大量的计算操作占用CPU,都会导致App界面卡顿。

推荐大神文章 https://www.androidperformance.com/2019/09/05/Android-Jank-Due-To-App/

卡顿分析工具

  • 用Systrace查看大致区间帧情况

    Systrace 是Android平台提供的一款工具( python 脚本文件,位于 Android SDK目录/platform-tools/systrace 中,其内部将调用 atrace 程序),用于记录短期内的设备活动。该工具会生成一份报告,其中汇总了Android 内核中的数据,例如 CPU 调度程序、磁盘活动和应用线程。Systrace主要用来分析绘制性能方面的问题。在发生卡顿时,通过这份报告可以知道当前整个系统所处的状态,从而帮助开发者更直观的分析系统瓶颈,改进性能。

    1.(非必须)在java代码中使用androidx.core.os.TraceCompat API ,为信息添加标签

    //标签为animator
    TraceCompat.beginSection("animator");
    //......
    TraceCompat.endSection();
    

    2.开始采样

    python systrace.py -t 5 -o [保存在电脑中的目录\dest.html] gfx input view am dalvik sched wm disk res -a [应用包名]
    

    3.使用chrome打开保存在电脑中的目录\dest.html文件

systrace.png

主要查看Frames中出现连续红色、黄色的点的区间段进行分析

推荐大神文章 https://androidperformance.com/2019/07/23/Android-Systrace-Pre/

  • App层面监控卡顿

    目前有两种主流有效的app监控方式:

    • 利用UI线程的Looper打印的日志,实现Printer接口并设置(BlockCanary)

      Looper在分发出来Message时,会打印耗时日志,并提供了设置打印机的方法

looper设置printer.png
looper的log.png
  • 使用Choreographer.FrameCallback获取帧率

    public static void start() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            Choreographer.getInstance().postFrameCallback(new Choreographer.FrameCallback() {
                long lastFrameTimeNanos = 0;
    
                @Override
                public void doFrame(long frameTimeNanos) {
                    //上次回调时间
                    if (lastFrameTimeNanos == 0) {
                        lastFrameTimeNanos = frameTimeNanos;
                        Choreographer.getInstance().postFrameCallback(this);
                        return;
                    }
                    long diff = (frameTimeNanos - lastFrameTimeNanos) / 1_000_000;
                    if (diff > 16.6f) {
                        //掉帧数
                        int droppedCount = (int) (diff / 16.6);
                    }
                    lastFrameTimeNanos = frameTimeNanos;
                    Choreographer.getInstance().postFrameCallback(this);
                }
            });
        }
    }
    

Looper方式比较适合在发布前进行测试或者小范围灰度测试然后定位问题,Choreographer方式适合监控线上环境的 app 的掉帧情况来计算 app 在某些场景的流畅度然后有针对性的做性能优化。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容