简体   繁体   中英

Frame rate reported by requestAnimationFrame is sometimes higher than the display's refresh rate

I'm using the following to record the frame rate of an application:

let _lastCalledTime;
let _fps;
let _frame = 0;
let _csv = 'Frame,Timestamp,FPS';

const _refreshLoop = () =>
    window.requestAnimationFrame((timestamp) => {
        if (!_lastCalledTime) {
            _lastCalledTime = timestamp;
            _fps = 0;
        } else {
            const delta = (timestamp - _lastCalledTime) / 1000;
            _lastCalledTime = timestamp;
            _fps = 1 / delta;
        }
        _csv += `\n${_frame++},${timestamp},${_fps}`;
        _refreshLoop();
    });

_refreshLoop();

Which is a variation of some code I found here: https://www.growingwiththeweb.com/2017/12/fast-simple-js-fps-counter.html

Every time a frame is rendered, the elapsed time since the last frame is calculated using the timestamp parameter passed to the callback. This is used to calculate the FPS and the values logged as a CSV.

I have a MacBook and a Raspberry Pi 3, both running at FPS, and I want to calculate the performance of the application. The MacBook reports a very precise value and, once stable, reports a value very close to 60 fps:

Frame Timestamp (ms) FPS
0 188.835 0
1 238.833 20.000800032001283
2 255.499 60.00240009600385
3 272.165 60.002400096003754
4 338.829 15.000600024000963
5 405.493 15.000600024000963
6 422.159 60.00240009600385
7 438.825 60.00240009600385
8 455.765 59.03187721369541
9 472.431 60.00240009600385
10 489.097 60.00240009600385
11 505.763 60.00240009600385
12 522.429 60.00240009600385
13 539.095 60.002400096003655
14 555.761 60.00240009600405

The Raspberry Pi has a less-precise reading for timestamp (1 ms) leading to a stable frame rate of 62.5/58.8 fps:

Frame Timestamp (ms) FPS
0 1303 0
1 1394 10.989010989010989
2 1411 58.8235294117647
3 1428 58.8235294117647
4 1444 62.5
5 1461 58.8235294117647
6 1477 62.5
7 1689 4.716981132075472
8 2321 1.5822784810126582
9 2443 8.19672131147541
10 2455 83.33333333333333
11 2487 31.25
12 2505 55.55555555555556
13 2521 62.5
14 2537 62.5

The bit that is confusing me is that the Raspberry Pi sometimes reports intervals of less than 16 ms, suggesting frame rates of much more than 60 fps, eg:

Frame Timestamp (ms) FPS
106 4378 40.00
107 4380 500.00
108 4397 58.82
109 4412 66.67
110 4428 62.50
111 4450 45.45
112 4462 83.33
113 4478 62.50

So my question is: how can this be? My initial thought was that multiple callbacks might be being called for the same frame, but in that case they would receive the same value for timestamp ( per the spec ). My two other suspicions are that, either timestamp is very inaccurate, or requestAnimationFrame() is not actually locked to the display's refresh rate and is sometimes executing faster.

requestAnimationFrame (rAF) is not "forced" to be locked to the display refresh rate no. A simple reason for that is that there may very well be no actual "display", eg in an headless browser. Still that browser will need rAF to fire at some interval.

You don't specify which browsers you are testing this on, but Chrome and Firefox will tie rAF to the V-Sync signal when there is one. I'm not sure what they do with adaptive sync monitors (like G-Sync) though. Also to be noted, the first call to rAF from a "non-animated" document, is actually scheduled to fire as soon as possible in both browsers.
Then in WebKit browsers, they don't look at the monitor at all and instead use a simple timer to try to reach 60FPS no matter the actual display rate. (Note that this is true only for rAF, CSS animations are synced to the monitor).

And this is all in agreement with the specs... which leave some leeway to the user-agent as to when it should update the rendering:

A browsing context has a rendering opportunity if the user agent is currently able to present the contents of the browsing context to the user, accounting for hardware refresh rate constraints and user agent throttling for performance reasons, but considering content presentable even if it's outside the viewport.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM