如何在Chrome开发者工具中获取FPS

14
我想要获取测量性能录制的平均fps。
到目前为止,我只能通过悬停在帧上或选择帧来获得每帧的持续时间和fps,如下所示:enter image description here enter image description here 要获得所有帧的平均fps,我需要逐个手动求和并计数,这非常不方便。

例如,Firefox开发工具显示面板右上角的平均fps。在此输入图片描述


页面上只有一个单独的FPS计量器叠加层,您可以在开发工具底部抽屉中启用它-> 渲染 -> FPS计量器 - wOxxOm
@drawer 但这只显示了当前的fps,而没有显示平均值,或者我漏掉了什么吗? - Robbendebiene
1
未实现,显然。另请参阅https://crbug.com/627925 - wOxxOm
如果您想要此功能,请在wOxxOm链接的Crbug问题下发表评论并加星标。目前,该问题被归档为低优先级。 - Kayce Basques
6个回答

24

您可以使用开发者工具的 devtools-for-devtools。

  1. 将开发者工具切换到独立窗口模式(点击开发者工具设置图标,点击“取消停靠”图标)。下一次,您只需按 Ctrl-Shift-D 键即可切换模式。
  2. 通过按下 Ctrl-Shift-i 来调用 devtools-for-devtools。

  • 显示所有帧的 FPS:

    UI.panels.timeline._flameChart._model._frameModel._frames.slice(1).map(f => +(1000 / f.duration).toFixed(1))

  • 显示平均 FPS:

    +UI.panels.timeline._flameChart._model._frameModel._frames.slice(1).map(f => 1000 / f.duration).reduce((avg, fps, i) => (avg*i + fps) / (i+1), 0).toFixed(1)

您可以将此代码保存为开发者工具片段面板中的片段,并在执行上述第 2 步后调用它。


2
太棒了!我不知道我可以在devtools窗口中使用devtools。 - Robbendebiene
只是为了那些可能困惑于在哪里添加此代码的人,一旦您打开了第二个DevTool,请将上述代码粘贴到控制台中。 - d13
语法有些变化:现在是 UI.panels.timeline.flameChart.model.frameModelInternal.frames.slice(1).map(f => +(1000 / f.duration).toFixed(1))UI.panels.timeline.flameChart.model.frameModelInternal.frames.slice(1).map(f => 1000 / f.duration).reduce((avg, fps, i) => (avg*i + fps) / (i+1), 0).toFixed(1) - Magoo

5
我要感谢@wOxxOm指出如何在上面的答案中访问DevTools的方法。
然而,给出用于计算平均FPS的代码并不完全正确。例如,如果有一帧需要一秒钟才能渲染,那么该帧的fps为1。如果还有另一帧需要(1000 / 60)毫秒才能渲染,那么该帧的fps为60。原始代码会为这两个帧提供一个错误的平均fps,即(60 + 1) / 2
正确的平均fps是总帧数除以总持续时间。在这个例子中,它是2 / (1 + 1 / 60) fps。
实现这个的一种方法是:
function averageFps() {
    let frames = UI.panels.timeline._flameChart._model._frameModel._frames;
    let duration = (frames[frames.length - 1].endTime - frames[0].startTime) / 1000;
    let average = frames.length / duration

    return +average.toFixed(2);
}

2

只是简单说明一下,API似乎稍微有些变化,所以现在实现此功能的新代码如下:

let frames = UI.panels.timeline.flameChart.model.frameModelInternal.frames;

let frameSet = [];
let startTimeMs = UI.panels.timeline.flameChart.model.window().left;
let endTimeMs = UI.panels.timeline.flameChart.model.window().right;

let minFPS = 1000;
let maxFPS = -1;
let totalFPS = 0;

for (let frameIdx in frames) {
    let frame = frames[frameIdx];
    if (frame.startTime >= startTimeMs && endTimeMs >= frame.endTime) {
        frameSet.push(frame);
        let frameRate = (16.0/frame.duration) * 60;
      
        if (maxFPS < frameRate) {
          maxFPS = frameRate;
        }        

        if (minFPS > frameRate) {
          minFPS = frameRate;
        }

        totalFPS += frameRate;
    }
}

console.log(`Total Frames: ${frameSet.length}`);
console.log(`Min FPS: ${minFPS}`);
console.log(`Max FPS: ${maxFPS}`);
console.log(`Average FPS: ${totalFPS / frameSet.length}`);

有人知道这个 UI API 是否有文档可供参考吗? - jwir3
我喜欢你的代码片段,但是在Chrome 97.0.4692.99版本中,我仍然需要使用API的下划线版本。新的API何时开始发挥作用? - Chris Blackwell
@Chris Blackwell 让我检查一下我的 Chrome 版本,然后回复你。 - jwir3
1
@ChrisBlackwell 看起来我在Ubuntu Linux上使用的是版本96.0.4664.110(实际上是PopOS,但它基于Ubuntu)。我想知道是否有可能我使用的是旧版API。我会看看能否调查一下。 - jwir3

1

更新了 @Daniel Le 的解决方案,考虑了当前选定的范围

var startTime = UI.panels.timeline._flameChart._model._window.left;
var endTime = UI.panels.timeline._flameChart._model._window.right;

var frames = UI.panels.timeline._flameChart._model._frameModel._frames
  .filter(frame => (frame.startTime > startTime) && (frame.endTime < endTime));

var duration = (frames[frames.length - 1].endTime - frames[0].startTime) / 1000;
var average = frames.length / duration

console.log(+average.toFixed(2));

0

开发工具的开发工具非常棒!

但是您的平均值没有考虑每帧的持续时间以及丢失或空闲帧,在给定这些持续时间[16,16,160]的情况下,您的代码将报告43.75 FPS的平均值,如果您正确地测量加权平均值,则FPS为15.62。

    // const frames = UI.panels.timeline.flameChart.model.frames().filter(({ idle }) => !idle);
    const frames = [{ duration: 16 }, { duration: 16 }, { duration:160 }]
    const totalDuration = frames.reduce((total, { duration }) => (total + duration), 0);
    const weightedFps = frames.map(f => [f.dropped ? 0 : 1000 / f.duration, f.duration])
      .reduce((avg, [fps, duration]) => avg + (fps * (duration / totalDuration)), 0);
    console.log(weightedFps);


0

更新的代码: 显示所有帧的FPS:

UI.panels.timeline.flameChart.model
.frameModel().frames.slice(1).map(f => +(1000 / f.duration).toFixed(1))

显示平均帧率:

UI.panels.timeline.flameChart.model.frameModel()
.frames.slice(1).map(f => 1000 / f.duration)
.reduce((avg, fps, i) => (avg*i + fps) / (i+1), 0).toFixed(1)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接