繁体   English   中英

requestAnimationFrame 报告的帧率有时高于显示器的刷新率

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

我正在使用以下内容来记录应用程序的帧速率:

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();

这是我在这里找到的一些代码的变体: https://www.growthwiththeweb.com/2017/12/fast-simple-js-fps-counter.html

每次渲染一帧时,使用传递给回调的timestamp参数计算自上一帧以来经过的时间。 这用于计算 FPS 和记录为 CSV 的值。

我有一个 MacBook 和一个 Raspberry Pi 3,都以 FPS 运行,我想计算应用程序的性能。 MacBook 报告了一个非常精确的值,一旦稳定,报告的值非常接近 60 fps:

框架 时间戳(毫秒) 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

Raspberry Pi 对timestamp (1 ms) 的读取精度较低,导致稳定的帧速率为 62.5/58.8 fps:

框架 时间戳(毫秒) 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

让我感到困惑的是,Raspberry Pi 有时会报告小于 16 毫秒的间隔,这表明帧速率远高于 60 fps,例如:

框架 时间戳(毫秒) 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

所以我的问题是:这怎么可能? 我最初的想法是,可能会为同一帧调用多个回调,但在这种情况下,它们会收到相同timestamp值( 根据规范)。 我的另外两个怀疑是,要么timestamp非常不准确,要么requestAnimationFrame()实际上没有锁定到显示器的刷新率,并且有时执行得更快。

requestAnimationFrame (rAF) 不会“强制”锁定到显示刷新率编号。 一个简单的原因是很可能没有实际的“显示”,例如在无头浏览器中。 该浏览器仍然需要 rAF 以某个时间间隔触发。

您没有指定要在哪些浏览器上进行测试,但 Chrome 和 Firefox 会将 rAF 绑定到 V-Sync 信号(如果有)。 不过,我不确定他们对自适应同步监视器(如 G-Sync)做了什么。 还要注意的是,从“非动画”文档对 rAF 的第一次调用实际上计划在两个浏览器中尽快触发。
然后在 WebKit 浏览器中,他们根本不看显示器,而是使用一个简单的计时器来尝试达到 60FPS,无论实际显示速率如何。 (请注意,这仅适用于 rAF,CSS 动画同步到监视器)。

这一切都与规范一致......这给用户代理留下了一些回旋余地,即何时应该更新渲染:

如果用户代理当前能够向用户呈现浏览上下文的内容,则浏览上下文具有呈现机会,考虑到硬件刷新率限制和用户代理出于性能原因而进行的节流,但考虑到即使内容在视口之外也是可呈现的.

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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