【性能优化】帧率优化方法:第一步——量化

Android计算帧率的几种方法

对于性能优化来说,要优化必先量化,如果没有量化则无法判断优化方向、优化策略是否正确,也就无法知道优化后是否取得了预期的成效。
应用在使用过程的卡顿感,一直是一个让人头疼的问题,因为他涉及到系统、应用交互的方方面面。包括:

  • cpu调度是否合理
  • 方法执行时长是否合理
  • 视图结构设计是否合理:有没有绘制性能更好的布局层次
  • binder调用是否卡顿:常见的主线程调用的binder接口,因系统资源紧张出现长耗时导致卡顿
  • io操作的延迟:io wait占比是否合理
    所以,帧率优化的第一步------量化,显得尤为重要,本文总结常见的三种计算帧率的方法,用于实际帧率优化过程中的方向指导。

一、注册编舞者doFrame

Android系统每隔16ms执行一次重绘任务是VSYNC信号驱动的,invalide/requestLayout->ViewRootImpl:performMeasure->ViewRootImpl:performLayout->ViewRootImpl:performDraw->SurfaceFlinger合成,这个过程就是视图的重绘流程。而ViewRootImpl中控制ui执行重绘就是通过注册编舞者的onFrame回调来完成的,因此我们也可以采用该方式来计算到帧率数据。代码如下:

java 复制代码
private long lastFrameTimeNanos = 0;
private int frameCount = 0;
private static final long FPS_INTERVAL = 1000_000_000;
Choreographer.getInstance().postFrameCallback(new Choreographer.FrameCallback() {
    @Override
    public void doFrame(long frameTimeNanos) {
        Log.d(TAG, "doFrame: " + frameTimeNanos);
        Choreographer.getInstance().postFrameCallback(this);
        //当前的帧率
        frameCount++;
        if (lastFrameTimeNanos > 0) {
           long interval = frameTimeNanos - lastFrameTimeNanos;
           // 间隔超过1s再计算fps值
           if (interval >= FPS_INTERVAL) {
             float fps = frameCount * 1_000_000_000f / interval;
             Log.d(TAG, "doFrame: fps = " + fps);
             frameCount = 0;
             lastFrameTimeNanos = frameTimeNanos;
          }
       } else {
             lastFrameTimeNanos = frameTimeNanos;
       }
      Choreographer.getInstance().postFrameCallback(this);
   }
 });
  • doFrame方法中的frameTimeNanos代表是每一帧的开始时间戳 ,用纳秒为单位,除以1000000就是毫秒为单位了。
    输出帧率计算结果:
java 复制代码
2025-10-05 19:32:46.762 29510-29510 Chor...itor com...catchanrlog  D  doFrame: fps = 58.56009
2025-10-05 19:32:47.770 29510-29510 Chor...itor com...catchanrlog  D  doFrame: fps = 60.547974
2025-10-05 19:32:48.777 29510-29510 Chor...itor com...catchanrlog  D  doFrame: fps = 60.547493
2025-10-05 19:32:49.785 29510-29510 Chor...itor com...catchanrlog  D  doFrame: fps = 60.547493
2025-10-05 19:32:50.791 29510-29510 Chor...itor com...catchanrlog  D  doFrame: fps = 60.646725
2025-10-05 19:32:51.797 29510-29510 Chor...itor com...catchanrlog  D  doFrame: fps = 60.584347

总结:该计算方式比较只算,是按照fps的定义直接计算出来的,不足之处是只有主线程的doFrame帧率,没法体现renderThread线程的丢帧情况,有一定的局限性。

二、使用dumpsys gfxinfo pkg_name计算帧率

dumpsys gfxinfo pkg_name

输出示例:

复制代码
Applications Graphics Acceleration Info:
Uptime: 63736043 Realtime: 63736043
** Graphics info for pid 23188 [com.tcl.cyberui] **
Stats since: 56002698393874ns
Total frames rendered: 130
Janky frames: 0 (0.00%)
Janky frames (legacy): 0 (0.00%)
50th percentile: 9ms
90th percentile: 11ms
95th percentile: 11ms
99th percentile: 11ms

计算帧率方法 :丢帧数的差值除以总绘制帧数的差值,得到丢帧率,再用1-丢帧率乘以60就得到帧率,如果是120刷新率的则把60换成120即可。

60 * (1 - (Janky frames2-Janky frames1/(Total frames rendered2-Total frames rendered1)))

三、抓取trace查看帧率

  • 1、使用atrace、systrace、或者perfetto等命令抓取trace文件
  • 2、把trace文件拖入https://ui.perfetto.dev/#!/打开,计算帧率
  • 3、帧率计算方式如下:
相关推荐
Zzzzzxl_14 小时前
互联网大厂前端面试实录:HTML5、ES6、Vue/React、工程化与性能优化全覆盖
性能优化·vue·es6·react·html5·前端面试·前端工程化
芝麻开门-新起点14 小时前
Flutter 移动端性能优化指南:内存、电量与 UI 渲染
flutter·ui·性能优化
奔跑的露西ly14 小时前
【HarmonyOS NEXT】常见的性能优化
华为·性能优化·harmonyos
007php00714 小时前
某游戏互联网大厂Java面试深度解析:Java基础与性能优化(一)
java·数据库·面试·职场和发展·性能优化·golang·php
wuk99814 小时前
Webpack技术深度解析:模块打包与性能优化
前端·webpack·性能优化
数据库生产实战15 小时前
Oracle RAC灾备环境UNDO表空间管理终极指南:解决备库修改难题与性能优化实战
数据库·oracle·性能优化
山河亦问安17 小时前
Spring Boot异步接口性能优化:从单线程到高并发的优化历程
spring boot·后端·性能优化
海边夕阳200617 小时前
PostgreSQL性能调优:解决表膨胀、索引碎片和无效索引问题
数据库·经验分享·postgresql·性能优化
腾飞开源1 天前
09_FastMCP 2.x 中文文档之FastMCP高级功能服务器组成详解
性能优化·代理服务器·模块化设计·fastmcp 2.x中文文档·服务器组合·前缀规则·标签过滤
Jinkxs2 天前
仓颉语言性能优化指南:实测对比,让鸿蒙应用运行效率提升 40%
华为·性能优化·harmonyos