How to calculate web animation frame rate FPS

Time:2021-7-1
catalogue
  • The standard of fluent animation
  • Method 1: with the help of chrome developer tools
  • Method 2: with the help of frame timing API
    • Blink kernel early architecture
    • The subtle difference between JS animation and CSS animation
    • What is the frame timing API?
    • Frame timing API
  • Method 3: with the help of the request animation frame API
    • Using request animation frame to calculate FPS principle

The standard of fluent animation

First, sort out some concepts. FPS represents the number of picture updates per second. We usually see a continuous picture is composed of a still picture, each picture is called a frame, FPS is a physical quantity to describe the “frame” change speed.

Theoretically, the higher the FPS is, the smoother the animation will be. At present, the screen refresh rate of most devices is 60 times / s, so generally speaking, the animation effect is the best when the FPS is 60 frame / s, that is, the consumption time of each frame is 16.67ms.

Of course, friends who often play FPS games must know that FPS games such as eating chicken / csgo recommend the use of 144hz refresh rate display. 144hz display refers to the display with 144hz refresh rate per second. Compared with the normal display refresh speed of 60 per second, the screen display is more fluent. Therefore, the 144hz display is more suitable for the first person shooting game where the viewing angle always keeps high speed.

However, this is only a high refresh rate feature provided by the monitor. For our web animation, it depends on the browser, and the refresh rate of most browsers is 60 times per second.

Intuitive experience, different frame rate experience:

  • If the frame rate can reach 50-60 FPS, the animation will be quite smooth and comfortable;
  • The animation with frame rate between 30 and 50 FPS varies from person to person in terms of sensitivity and comfort;
  • Animation with frame rate below 30 FPS makes people feel obviously stuck and uncomfortable;
  • Animation with great frame rate fluctuation can also make people feel stuck.

OK, so how can we accurately get the current FPS value of our page animation?

Method 1: with the help of chrome developer tools

Chrome provides powerful functions for developers. In the developer tool, we can call up the FPS meter option as follows:

With this button, you can start the real-time frame rate observation and page GPU utilization.

Disadvantages:

  • This can only observe a few pages at a time, and it needs to be observed manually in real time
  • Data can only be subjective feelings, and there is not a very accurate data constantly reported or collected

So we need a more intelligent approach.

Method 2: with the help of frame timing API

Before introducing the following method, continue to do some basic knowledge popularization.

Blink kernel early architecture

Take blink rendering page as an example. For the early Chrome browser, each page tab corresponds to an independent render process, which includes the main thread and synthesis thread. Early chrome kernel architecture:

The main thread is mainly responsible for:

  • Calculation and execution of JavaScript
  • CSS style calculation
  • Layout calculation
  • Drawing page elements as a bitmap (paint), that is, rasterization (rasterization)
  • Give bitmap to composition thread

The composition thread is mainly responsible for:

  • Upload the bitmap (graphics layer) to GPU in the form of texture
  • Calculate the visible and upcoming visible parts of the page (scrolling)
  • CSS animation processing
  • Tells the GPU to draw a bitmap to the screen

OK, in the clouds, something. In fact, after knowing these two threads, the next concept is to clarify the subtle differences between CSS animation and JS animation (of course, they are web animation).

The subtle difference between JS animation and CSS animation

For JS animations, their run-time frame rate is the total time consumed by the main thread and synthesis thread. For smooth animation, we hope that the time consumption of each frame is kept within 16.67ms;

For CSS animation, because its process is not affected by the main thread, we hope to get the time consumed by the synthesis thread, and the drawing frequency of the synthesis thread also reflects the process of scrolling and CSS animation.

The main conclusion I want to draw above is. If we can know the time consumed by each frame of the main thread and synthesis thread, we can roughly get the frame rate of the corresponding web animation. So can the frame timing API mentioned above help us get to this point in time.

What is the frame timing API?

Frame timing API is one of the members of Web Performance timing API standard.

Web performance timing API is a set of performance API standards launched by W3C, which is used to help developers accurately analyze and control all aspects of website performance, and improve the performance of Web sites.

It contains many subclasses of API, which perform different functions, as follows (excerpt from using performance API to quickly analyze web front-end performance, of course, you can also see the introduction of the original English version: Web Performance timing API)

How to use it? Take navigation timing, performance timeline and resource timing as examples. For browsers compatible with it, it is exposed and mounted on window.performance in the form of read-only attributes.

Print window.performance in the console, and check the timing property

What do a series of variables in this object represent? It represents every important time point in the whole loading process of our page. You can take a detailed look at this figure

Through this figure and the above window.performance.timing, we can easily count the time consumption of each important node on the page. This is the strength of the web performance timing API. Those who are interested can study it in detail and use it in page statistics.

Frame timing API

OK, we can finally get back to the point. With the help of frame timing API in Web Performance timing API, we can easily get the time of main thread and synthesis thread in each frame. Or it’s easier to get the time of each frame.

Obtain the records of the render main thread and the composition thread. The information contained in each record is basically as follows, and the code is illustrated (refer to the developer feedback needed: frame timing API)


var rendererEvents = window.performance.getEntriesByType("renderer");
var compositeThreadEvents = window.performance.getEntriesByType("composite");

Or:


var observer = new PerformanceObserver(function(list) {
    var perfEntries = list.getEntries();
    for (var i = 0; i < perfEntries.length; i++) {
        console.log("frame: ", perfEntries[i]);
    }
});
 
// subscribe to Frame Timing
observer.observe({entryTypes: ['frame']});

The information contained in each record is basically as follows:


{
  sourceFrameNumber: 120,
  startTime: 1342.549374253
  cpuTime: 6.454313323
}

Each record includes a unique frame number, frame start time, and CPU time. By calculating the start time of each record, we can calculate the interval between every two frames, so as to get whether the frame rate of the animation can reach 60 FPS.

however! Take a look at the overall compatibility of the web performance timing API:

Although the frame timing API is good, the compatibility of the frame timing API is not very friendly now. Well, how unfriendly is it. No browser support, in the experimental stage, belongs to the future oriented programming. Are you kidding me? I can’t use it after so long

Method 3: with the help of the request animation frame API

It took so much time to describe the frame timing API, but in the end, because of compatibility problems, it couldn’t be used at all. However, it does not mean that such a long description is useless. From the above introduction, we know that if we can get a fixed time point in each frame, then subtracting the two can also approximate the time consumed by a frame.

Well, let’s find another way. This time, we use the well compatible request animation frame API.

//Grammar
window.requestAnimationFrame(callback);

The method tells the browser that you want to execute the animation and requests the browser to call the specified function to update the animation before the next redraw.

You apply this method when you are ready to update the screen. This will require your animation function to be executed before the next redraw in the browser. The number of callbacks is usually 60 per second, and most browsers usually match the W3C recommended refresh rate.

Using request animation frame to calculate FPS principle

The principle is that normally, the method of request animation frame will be executed 60 times in a second, that is, without dropping the frame. Suppose the animation starts at time a and ends at time B, taking x Ms. If the middle request animation frame is executed n times, the frame rate of this animation is n / (B – a).

The core code is as follows, which can approximately calculate the page frame rate per second, and we record an extra allframecount, which is used to record the execution times of RAF and calculate the frame rate of each animation

var rAF = function () {
    return (
        window.requestAnimationFrame ||
        window.webkitRequestAnimationFrame ||
        function (callback) {
            window.setTimeout(callback, 1000 / 60);
        }
    );
}();
  
var frame = 0;
var allFrameCount = 0;
var lastTime = Date.now();
var lastFameTime = Date.now();
  
var loop = function () {
    var now = Date.now();
    var fs = (now - lastFameTime);
    var fps = Math.round(1000 / fs);
  
    lastFameTime = now;
    //Do not set to 0, record the difference of this value at the beginning and end of the animation to calculate FPS
    allFrameCount++;
    frame++;
  
    if (now > 1000 + lastTime) {
        var fps = Math.round((frame * 1000) / (now - lastTime));
        Console. Log ('${new date()} 1s, FPS:', FPS);
        frame = 0;
        lastTime = now;
    };
  
    rAF(loop);
}
 
loop();

OK, find a page with animation running continuously to test. You can see that the code runs as follows:

Here, I used a page that I made before to test. I used chrome to call out the FPS meter of the page at the same time, and compared the real-time FPS values on both sides, which basically matched.

Test page, solar system. You can paste the above code into the console of this page to test the data:

Compared with the frame rate in the upper right corner, the frame rate is basically the same. In most cases, this method can get the frame rate of Web animation very well.

If we need to count the frame rate of a specific animation process, we only need to record the value of allframecount at the beginning and end of the animation, and then divide it by the time consumed in the middle to get the FPS value of a specific animation process.

It is worth noting that there must be an error between the calculation result of this method and the real frame rate, because it takes the time interval between every two main threads executing JavaScript as one frame, rather than the time consumed by the main thread plus synthetic thread as one frame. But for the present stage, it is a desirable method.

The above is how to calculate the web animation frame rate FPs in detail. For more information about calculating the web animation frame rate FPS, please pay attention to other related articles of developer!