前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >[036]Choreographer Skipped真正含义

[036]Choreographer Skipped真正含义

作者头像
王小二
发布于 2020-06-08 04:06:27
发布于 2020-06-08 04:06:27
1.7K00
代码可运行
举报
运行总次数:0
代码可运行

前言

我相信大家肯定遇到过下面这个LOG,表面意思是在主线程做了太多的事,但是可能你们不知道这条LOG的真实含义。换句话说你们能写一个Demo生成这条LOG吗?我建议你们先写写看,再继续看下去。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Choreographer: Skipped 60 frames!  The application may be doing too much work on its main thread.

一、可能是大多数人的Demo

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
    }

    @Override
    protected void onResume() {
        Log.d("KobeWang", "MainActivity : onResume start");
        super.onResume();
        try {
            Thread.sleep(1000);
        } catch (Exception e) {

        }
        Log.d("KobeWang", "MainActivity : onResume end");
    }
}

我相信大多数人写的Demo是上面这样子的,但是很遗憾,不会出现Choreographer Skipped的LOG,就算把1000ms改成10s,也不会出现。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
03-11 19:01:25.679 15733 15733 D KobeWang: MainActivity : onResume start
03-11 19:01:26.682 15733 15733 D KobeWang: MainActivity : onResume end

二、Choreographer Skipped

2.1 那我们来分析一下Choreographer Skipped生成的流程

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    private Choreographer(Looper looper, int vsyncSource) {
        ...
        //每一帧的时间,如果60hz的屏幕,就是16ms,但是这里是微秒
        mFrameIntervalNanos = (long)(1000000000 / getRefreshRate())
        ...
    }

    private final class FrameDisplayEventReceiver extends DisplayEventReceiver
            implements Runnable {

        private long mTimestampNanos;
        private int mFrame;

        @Override
        public void onVsync(long timestampNanos, long physicalDisplayId, int frame) {
            ...
            //onVsync方法将会在Vsync信号接收之后被回调
            //mTimestampNanos就是这次Vsync信号接收的时间
            mTimestampNanos = timestampNanos;
            mFrame = frame;
            //往主线程的Looper中投放一个Asynchronous的Message,callback为this
            //这个Message被处理的时候就会调用下面run-doFrame的方法
            Message msg = Message.obtain(mHandler, this);
            msg.setAsynchronous(true);
            mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
        }

        @Override
        public void run() {
            doFrame(mTimestampNanos, mFrame);
        }
    }

    void doFrame(long frameTimeNanos, int frame) {
        final long startNanos;
        synchronized (mLock) {
            ...
            //intendedFrameTimeNanos就是预计执行doFrame的时间点
            long intendedFrameTimeNanos = frameTimeNanos;
            //startNanos就是实际执行doFrame的时间点
            startNanos = System.nanoTime();
            //计算实际和预计的时间差
            final long jitterNanos = startNanos - frameTimeNanos;
            //如果时间差大于一帧的时间,也就是16ms
            if (jitterNanos >= mFrameIntervalNanos) {
                //计算丢掉的帧数=时间差/一帧的时长
                final long skippedFrames = jitterNanos / mFrameIntervalNanos;
                //SKIPPED_FRAME_WARNING_LIMIT默认是30
                if (skippedFrames >= SKIPPED_FRAME_WARNING_LIMIT) {
                    //如果丢掉的帧数大于30帧就打印LOG
                    Log.i(TAG, "Skipped " + skippedFrames + " frames!  "
                            + "The application may be doing too much work on its main thread.");
                }
             
            }
            ...
        }
    }

第一步:onVsync方法中保存Vsync信号接收的时间点timestampNanos

第二步:doFrame方法中计算时间差jitterNanos=当前时间-timestampNanos

第三步:如果时间差jitterNanos大于mFrameIntervalNanos(16ms),计算丢失的帧数skippedFrames=jitterNanos/mFrameIntervalNanos

第四步:如果skippedFrames大于30帧,打印Choreographer Skipped

2.2 onVsync方法什么时候被调用

监听到Vsync信号就会调用onVsync

如何监听Vsync信号?

首先要调用ViewRootImpl.scheduleTraversals,对下一个Vsync信号进行监听。

MainActivity的onResume完成之后就会触发ViewRootImpl.scheduleTraversals。

有兴趣的可以看看下面整个调用逻辑

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
KobeWang: java.lang.Exception: KobeWang
KobeWang:   at android.view.ViewRootImpl.scheduleTraversals(ViewRootImpl.java:1694)
KobeWang:   at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:1425)
KobeWang:   at android.view.ViewRootImpl.setView(ViewRootImpl.java:856)
KobeWang:   at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:387)
KobeWang:   at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:96)
KobeWang:   at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:4399)
KobeWang:   at android.app.servertransaction.ResumeActivityItem.execute(ResumeActivityItem.java:52)
KobeWang:   at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:176)
KobeWang:   at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
KobeWang:   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2102)
KobeWang:   at android.os.Handler.dispatchMessage(Handler.java:107)
KobeWang:   at android.os.Looper.loop(Looper.java:214)
KobeWang:   at android.app.ActivityThread.main(ActivityThread.java:7501)
KobeWang:   at java.lang.reflect.Method.invoke(Native Method)
KobeWang:   at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
KobeWang:   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:935)
小结:onVsync方法将会在onResume完成之后的下一个Vsync信号接收的时候被调用。

2.3 doFrame方法什么时候被调用

onVsync方法中往主线程的Looper中投放一个Asynchronous的Message。

这个Asynchronous的Message什么时候被处理,doFrame就是什么时候被调用。

整个Message的处理流程有兴趣的可以看我朋友的文章 https://zhenkunhuang.github.io/2019/05/05/android-handler-java/

小结:主线程Looper会是按照Message.when时间以及入队顺序执行,如果遇到一个同步屏障的message,从队列中选取最靠前的Asynchronous的Message优先处理。

Asynchronous的Message是Android隐藏接口,主要是系统用于UI显示的Message,从侧面也是看出安卓设计的初衷UI相关的Message优先处理。

2.4 总结

Choreographer Skipped真正反映的是onVsync和doFrame两个方法调用的时间间隔

其实这句话并不准确,我在[037]Choreographer Skipped含义再探中进行了修正。

三、我的Demo

前面的Demo为什么会失败是因为在onResume中sleep 1000ms,只能整体推迟调用onVsync和doFrame而已,并不能增加onVsync和doFrame之间调用的时间。

如何增加onVsync和doFrame之间调用的时间

如果在onVsync方法中投放Asynchronous的Message之前,主线程Looper有未处理的Message,就可以增加onVsync和doFrame两个方法调用的时间间隔,就会打印出Choreographer Skipped的LOG。

我写了如下的Demo

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class MainActivity extends AppCompatActivity {

    private Handler mHandler = new Handler();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
    }

    @Override
    protected void onResume() {
        Log.d("KobeWang", "MainActivity : onResume start");
        super.onResume();
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (Exception e) {

                }
            }
        });
        Log.d("KobeWang", "MainActivity : onResume end");
    }
}

我在onResume完成之前,post了一个Runnable,也就是普通Message,并且Runnable休眠了1000ms。看我运行的LOG,果然出现了 Skipped 60 frames,正好和休眠的1000ms对应上。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
2020-03-11 19:19:38.281 19118-19118/com.kobe.jankblock D/KobeWang: MainActivity : onResume start
2020-03-11 19:19:38.281 19118-19118/com.kobe.jankblock D/KobeWang: MainActivity : onResume end
2020-03-11 19:19:39.294 19118-19118/com.kobe.jankblock I/Choreographer: Skipped 60 frames!  The application may be doing too much work on its main thread.

四、为什么要理解Choreographer Skipped

因为在解决性能问题的时候,尤其是解决启动慢,丢帧问题的时候,大家要完整的梳理整个主线程中处理所有的Message任务,然后自己想办法写出Demo模拟,这样子才能从根本上解决这类性能问题,而不是简单的一句“少在主线程中做事情”,就可以解决问题。我在[035] onStop提前投放问题中就按照这个思路解决了一个启动慢的问题。

尾巴

[037]Choreographer Skipped含义再探中我会介绍另外一种Demo。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
ACMSGURU 114 - Telecasting station
Every city in Berland is situated on Ox axis. The government of the country decided to build new telecasting station. After many experiments Berland scientists came to a conclusion that in any city citizens displeasure is equal to product of citizens amount in it by distance between city and TV-station. Find such point on Ox axis for station so that sum of displeasures of all cities is minimal.
Reck Zhang
2021/09/01
5490
ACMSGURU 275 - To xor or not to xor
The sequence of non-negative integers A1, A2, …, AN is given. You are to find some subsequence Ai1, Ai2, …, Aik (1 <= i1 < i2 < … < ik <= N) such, that Ai1 XOR Ai2 XOR … XOR Aik has a maximum value.
Reck Zhang
2021/08/11
3640
C++版 - 剑指Offer 面试题36:数组中的逆序对及其变形(Leetcode 315. Count of Smaller Numbers After Self)题解
题目:在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
Enjoy233
2019/03/05
1.4K0
C++版 - 剑指Offer 面试题36:数组中的逆序对及其变形(Leetcode 315. Count of Smaller Numbers After Self)题解
ACMSGURU 507 - Treediff
Andrew has just made a breakthrough in complexity theory: he thinks that he can prove P=NP if he can get a data structure which allows to perform the following operation quickly. Naturally, you should help him complete his brilliant research. Consider a rooted tree with integers written in the leaves. For each internal (non-leaf) node v of the tree you must compute the minimum absolute difference between all pairs of numbers written in the leaves of the subtree rooted at v.
Reck Zhang
2021/08/11
4170
ACMSGURU 507 - Treediff
ACMSGURU 154 - Factorial
You task is to find minimal natural number N, so that N! contains exactly Q zeroes on the trail in decimal notation. As you know N! = 12…*N. For example, 5! = 120, 120 contains one zero on the trail.
Reck Zhang
2021/08/11
2900
ACMSGURU 101 - Domino
Dominoes – game played with small, rectangular blocks of wood or other material, each identified by a number of dots, or pips, on its face. The blocks usually are called bones, dominoes, or pieces and sometimes men, stones, or even cards. The face of each piece is divided, by a line or ridge, into two squares, each of which is marked as would be a pair of dice…
Reck Zhang
2021/08/11
4940
ACMSGURU 104 - Little shop of flowers
You want to arrange the window of your flower shop in a most pleasant way. You have F bunches of flowers, each being of a different kind, and at least as many vases ordered in a row. The vases are glued onto the shelf and are numbered consecutively 1 through V, where V is the number of vases, from left to right so that the vase 1 is the leftmost, and the vase V is the rightmost vase. The bunches are moveable and are uniquely identified by integers between 1 and F. These id-numbers have a significance: They determine the required order of appearance of the flower bunches in the row of vases so that the bunch i must be in a vase to the left of the vase containing bunch j whenever i < j. Suppose, for example, you have bunch of azaleas (id-number=1), a bunch of begonias (id-number=2) and a bunch of carnations (id-number=3). Now, all the bunches must be put into the vases keeping their id-numbers in order. The bunch of azaleas must be in a vase to the left of begonias, and the bunch of begonias must be in a vase to the left of carnations. If there are more vases than bunches of flowers then the excess will be left empty. A vase can hold only one bunch of flowers.
Reck Zhang
2021/08/11
4540
ACMSGURU 398 - Friends of Friends
Social networks are very popular now. They use different types of relationships to organize individual users in a network. In this problem friendship is used as a method to connect users. For each user you are given the list of his friends. Consider friendship as a symmetric relation, so if user a is a friend of user b then b is a friend of a.
Reck Zhang
2021/08/11
2310
ACMSGURU 231 - Prime Sum
Find all pairs of prime numbers (A, B) such that A<=B and their sum is also a prime number and does not exceed N.
Reck Zhang
2021/08/11
3280
ACMSGURU 130 - Circle
On a circle border there are 2k different points A1, A2, …, A2k, located contiguously. These points connect k chords so that each of points A1, A2, …, A2k is the end point of one chord. Chords divide the circle into parts. You have to find N - the number of different ways to connect the points so that the circle is broken into minimal possible amount of parts P.
Reck Zhang
2021/08/11
2640
数据结构之快速排序
上次讲了基于分治法的归并排序,可是归并排序有许多缺点,比如它需要占用额外的内存来存储所需排序的数组,并且整个排序最重要的就是用来合并数组的函数。我写了几次发现,这个合并数组的函数写起来感觉有点麻烦啊!
灯珑LoGin
2022/10/31
4000
数据结构之快速排序
ACMSGURU 134 - Centroid
You are given an undirected connected graph, with N vertices and N-1 edges (a tree). You must find the centroid(s) of the tree. In order to define the centroid, some integer value will be assosciated to every vertex. Let’s consider the vertex k. If we remove the vertex k from the tree (along with its adjacent edges), the remaining graph will have only N-1 vertices and may be composed of more than one connected components. Each of these components is (obviously) a tree. The value associated to vertex k is the largest number of vertices contained by some connected component in the remaining graph, after the removal of vertex k. All the vertices for which the associated value is minimum are considered centroids.
Reck Zhang
2021/08/11
2680
基础知识_算法笔记
1342. Number of Steps to Reduce a Number to Zero
yifei_
2022/11/14
1.6K0
基础知识_算法笔记
ACMSGURU 113 - Nearly prime numbers
Nearly prime number is an integer positive number for which it is possible to find such primes P1 and P2 that given number is equal to P1*P2. There is given a sequence on N integer positive numbers, you are to write a program that prints “Yes” if given number is nearly prime and “No” otherwise.
Reck Zhang
2021/08/11
3540
ACMSGURU 499 - Greatest Greatest Common Divisor
Andrew has just made a breakthrough in sociology: he realized how to predict whether two persons will be good friends or not. It turns out that each person has an inner friendship number (a positive integer). And the quality of friendship between two persons is equal to the greatest common divisor of their friendship number. That means there are prime people (with a prime friendship number) who just can’t find a good friend, andWait, this is irrelevant to this problem. You are given a list of friendship numbers for several people. Find the highest possible quality of friendship among all pairs of given people. Input The first line of the input file contains an integer n (2 <= n <= 10000) — the number of people to process. The next n lines contain one integer each, between 1 and 1000000(inclusive), the friendship numbers of the given people. All given friendship numbers are distinct. Output Output one integer — the highest possible quality of friendship. In other words, output the greatest greatest common divisor among all pairs of given friendship numbers.
Reck Zhang
2021/08/11
4060
ACMSGURU 133 - Border
Along the border between states A and B there are N defence outposts. For every outpost k, the interval [Ak,Bk] which is guarded by it is known. Because of financial reasons, the president of country A decided that some of the outposts should be abandoned. In fact, all the redundant outposts will be abandoned. An outpost i is redundant if there exists some outpost j such that Aj<Ai and Bi<Bj. Your task is to find the number of redundant outposts.
Reck Zhang
2021/08/11
3920
ACMSGURU 117 - Counting
Find amount of numbers for given sequence of integer numbers such that after raising them to the M-th power they will be divided by K.
Reck Zhang
2021/08/11
2760
ACMSGURU 118 - Digital Root
Let f(n) be a sum of digits for positive integer n. If f(n) is one-digit number then it is a digital root for n and otherwise digital root of n is equal to digital root of f(n). For example, digital root of 987 is 6. Your task is to find digital root for expression A1*A2*...*AN + A1*A2*...*AN-1 + ... + A1*A2 + A1.
Reck Zhang
2021/08/11
3080
ACMSGURU 123 - The sum
The Fibonacci sequence of numbers is known: F1 = 1; F2 = 1; Fn+1 = Fn + Fn-1, for n>1. You have to find S - the sum of the first K Fibonacci numbers.
Reck Zhang
2021/08/11
4030
ACMSGURU 127 - Telephone directory
CIA has decided to create a special telephone directory for its agents. The first 2 pages of the directory contain the name of the directory and instructions for agents, telephone number records begin on the third page. Each record takes exactly one line and consists of 2 parts: the phone number and the location of the phone. The phone number is 4 digits long. Phone numbers cannot start with digits 0 and 8. Each page of the telephone directory can contain not more then K lines. Phone numbers should be sorted in increasing order. For the first phone number with a new first digit, the corresponding record should be on a new page of the phone directory. You are to write a program, that calculates the minimal number P pages in the directory. For this purpose, CIA gives you the list of numbers containing N records, but since the information is confidential, without the phones locations.
Reck Zhang
2021/08/11
3320
相关推荐
ACMSGURU 114 - Telecasting station
更多 >
LV.1
TencentGame Developer
目录
  • 前言
  • 一、可能是大多数人的Demo
  • 二、Choreographer Skipped
    • 2.1 那我们来分析一下Choreographer Skipped生成的流程
    • 2.2 onVsync方法什么时候被调用
    • 2.3 doFrame方法什么时候被调用
    • 2.4 总结
  • 三、我的Demo
    • 如何增加onVsync和doFrame之间调用的时间
    • 我写了如下的Demo
  • 四、为什么要理解Choreographer Skipped
  • 尾巴
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档