Skip to content

Stage05|Performance ​

Lesson056|FPS、Frame Time、刷新率与帧预算 ​

Tags: #Creator2.x #Stage05 #FPS #FrameTime #FrameBudgetDifficulty: ⭐⭐⭐☆☆


真实问题:平均 60 FPS,为什么玩家仍觉得卡 ​

10 秒内大多数帧约 16 ms,但每秒有一帧达到 100 ms。平均 FPS 仍可能接近 60,玩家却会稳定感到顿一下。

text
平均值隐藏了长帧
长帧决定可感知卡顿

性能验收需要 Frame Time 分布和高分位,而不只是平均 FPS。

一、本课目标 ​

本课把“帧率”转换成可计算的帧预算:

  • FPS 和 Frame Time 的关系。
  • 为什么平均 FPS 会掩盖尖峰。
  • 16.67 ms 到底代表什么。
  • 如何为 CPU、GPU 和加载阶段分配预算。

二、FPS 和 Frame Time ​

text
Frame Time = 1 秒 / FPS
FPS = 1 秒 / Frame Time

常用目标:

FPS单帧时间
3033.33 ms
6016.67 ms
9011.11 ms
1208.33 ms

60 FPS 的目标不是“每秒调用 60 次”这么简单,而是每帧所有 CPU、GPU 和同步工作都尽量落在约 16.67 ms 内。


三、平均值为什么不够 ​

两组帧时间:

text
A:16, 16, 17, 16, 16
B:5, 5, 5, 5, 85

B 的平均值可能看起来不差,但 85 ms 的尖峰会明显造成卡顿。实际分析应关注:

text
平均值
P95 / P99
最大帧时间
尖峰出现位置

四、帧预算不是只有一份 ​

一帧可以粗略拆成:

text
CPU 业务和引擎更新
CPU 渲染准备和提交
GPU 顶点和像素处理
输入、音频、网络等其他工作

CPU 和 GPU 可能并行,但最终帧完成时间受更慢的一侧以及同步点限制。不要简单把 16.67 ms 平均切成“CPU 8 ms、GPU 8 ms”就当作万能标准,应通过工具观察真实瓶颈。


五、刷新率和目标帧率 ​

屏幕刷新率是显示设备能力,游戏 FPS 是应用实际提交速度:

text
120 Hz 屏幕不保证游戏 120 FPS
60 FPS 游戏也可能运行在 120 Hz 屏幕

如果目标 60 FPS,单帧预算约 16.67 ms;如果设备只有 30 FPS,预算约 33.33 ms。移动端应以目标机型和产品体验确定预算,而不是只看开发机。


六、帧时间尖峰的常见来源 ​

  • GC 或大量临时对象。
  • 场景切换和资源解码。
  • 首次创建纹理或 Shader。
  • Layout / Widget 批量重算。
  • 大量 Node 创建和销毁。
  • 同步等待 GPU 或 IO。
  • 日志、调试绘制和 Profiler 自身开销。

尖峰排查要关联时间线,不能只看某一个函数的平均耗时。


七、案例:同样 55 FPS 的两个页面 ​

页面 A:

text
每帧稳定约 18 ms

页面 B:

text
大部分帧 10 ms
每隔几秒出现 100 ms

页面 A 是持续超预算,页面 B 是尖峰问题。优化策略不同:

  • A:减少每帧持续工作。
  • B:找到周期性任务、加载、GC 或同步点。

八、性能记录表 ​

建议记录:

text
设备:型号、系统、分辨率
场景:入口和操作步骤
目标:30 / 60 / 120 FPS
CPU Frame Time:平均、最大、P95
GPU Frame Time:平均、最大、P95
内存:初始、峰值、场景后
版本:构建号和资源版本

没有这些信息,优化前后的“变快”很难复现。


九、常见误区 ​

误区一:FPS 从 60 变 55 就一定是严重问题 ​

需要看帧时间分布、设备目标和用户是否感知到尖峰。

误区二:平均 FPS 高就没有卡顿 ​

尖峰可能被平均值掩盖。

误区三:刷新率越高就必须让游戏跑得越快 ​

需要根据产品目标、设备功耗和逻辑稳定性决定。

误区四:只为 CPU 分配预算 ​

GPU、IO、内存和同步也会限制一帧完成时间。


十、练习与答案 ​

  1. 60 FPS 的单帧预算是多少?
  2. 为什么 P95/P99 比单纯平均值更有价值?
  3. 5 ms、5 ms、5 ms、100 ms 的问题属于持续超预算还是尖峰?
  4. 为什么需要记录设备、分辨率和构建版本?

答案:

  1. 约 16.67 ms。
  2. 它们能反映尾部延迟和用户感知到的卡顿。
  3. 尖峰问题。
  4. 性能受硬件、分辨率、平台和资源版本影响,必须保证可复现。

帧预算先从目标推导 ​

text
60 FPS → 每帧约 16.67 ms
30 FPS → 每帧约 33.33 ms
120 FPS → 每帧约 8.33 ms

这是总预算,不是 JavaScript 可以独占的预算。还要留给引擎、渲染提交、GPU、平台调度等。

若 GPU 需要 20 ms,即使 CPU 只用 5 ms,也无法稳定 60 FPS。CPU/GPU 是否并行以及工具如何显示,取决于平台。

Creator 2.4.x 实验:记录长帧而不是平均值 ​

FrameTimeProbe.ts ​

ts
const { ccclass } = cc._decorator;

@ccclass
export default class FrameTimeProbe extends cc.Component {
    private samples: number[] = [];
    private elapsed = 0;

    update(dt: number) {
        this.samples.push(dt * 1000);
        this.elapsed += dt;

        if (this.elapsed >= 10) {
            this.report();
            this.samples.length = 0;
            this.elapsed = 0;
        }
    }

    createSpike() {
        const begin = Date.now();
        while (Date.now() - begin < 80) {
            // 测试场景中故意阻塞主线程。
        }
    }

    private report() {
        const sorted = this.samples.slice().sort((a, b) => a - b);
        const percentile = (ratio: number) => {
            const index = Math.min(
                sorted.length - 1,
                Math.floor(sorted.length * ratio)
            );
            return sorted[index].toFixed(2);
        };

        cc.log(
            '[frame]',
            'count=', sorted.length,
            'p50=', percentile(0.5),
            'p95=', percentile(0.95),
            'p99=', percentile(0.99),
            'max=', sorted[sorted.length - 1].toFixed(2)
        );
    }
}

dt 是游戏循环提供的时间间隔,并非硬件级精确 CPU 测量;实验用于观察长帧分布,正式分析结合 Profiler。

步骤 ​

  1. 静置 10 秒记录基线。
  2. 每秒触发一次 80 ms Spike。
  3. 比较平均 FPS 与 p95/p99/max。
  4. 在 30/60 目标帧率设置下分别测试。
  5. 记录设备刷新率与是否连接调试器。

为什么 55 FPS 可能代表两种体验 ​

text
页面 A:帧时间稳定约 18 ms
页面 B:大多数 16 ms,偶尔 80~150 ms

两者平均 FPS 可以接近,B 的顿挫更明显。报告至少包含:

  • 中位数;
  • p95/p99;
  • 最大帧;
  • 超预算帧比例;
  • 测试时长;
  • 用户动作时间点。

VSync 与刷新率的台阶 ​

当渲染不能赶上刷新窗口,呈现可能从 60 附近掉到更低台阶,具体取决于平台的交换与调度。不要把 30 FPS 简单理解为代码正好耗时 33 ms。

高刷新率设备上,60 FPS 可能仍是项目目标;必须记录:

text
设备刷新率
游戏目标帧率
实际呈现帧率
CPU/GPU 帧时间

真实项目故障:每秒整点顿一下 ​

通过时间线发现每秒 p99 峰值。代码在整秒同时做:

text
更新 100 个倒计时 Label
→ 刷新 Layout
→ 保存本地进度
→ 上报埋点

优化不是把四项都删掉,而是:

  • Label 仅更新可见项;
  • 固定布局尺寸;
  • 存档与上报错峰;
  • 合并序列化;
  • 对比 p99 与功能正确性。

版本边界与练习答案 ​

Creator 2.4.x 的 dt、目标帧率与平台呈现受浏览器/原生调度影响。精确帧时间应结合平台工具。

  1. 60 FPS 的理论预算是多少? 约 16.67 ms 总帧预算。
  2. 为什么平均 FPS 不能发现规律尖峰? 少数长帧会被大量正常帧稀释,而玩家对长帧敏感。
  3. p99 表示什么? 约 99% 样本不超过该值,最慢约 1% 帧达到或超过附近范围。
  4. 优化目标为什么应写“p99 < X”而非“更流畅”? 前者可测、可回归、可判断是否达标。

十一、本课总结 ​

text
FPS 是结果,Frame Time 是成本。
帧预算要看分布,不能只看平均值。
目标设备和刷新率决定实际预算。
持续超预算和偶发尖峰需要不同排查路径。

十二、下一课预告 ​

text
Lesson057|Creator Profiler 应该怎么看?