Android性能之——线上帧率检测的实现
Android性能之——帧率检测
本文我们来学习如何实现帧率的检测。
为什么要检测帧率
Android在设计的时候,把帧频限定在了每秒60帧,当我们的APP的帧频60fps时,画面就会非常的流程。但是通常由于各种各样的原因,帧频很可能会小于60fps,这样就会出现丢帧现象,用户端表现为可感知的卡顿等现象。那面我们的帧频可以高于60fps吗,答案是否定的,这是因为界面刷新渲染依赖底层的VSYNC信号,VSYNC信号以每秒60次的频率发送给上层,并且高于60fps的帧频也是没有必要的,因为人眼与大脑之间的协作无法感知超过60fps的画面更新。
12fps大概类似手动快速翻动书籍的帧率,这明显是可以感知到不够顺滑的。24fps使得人眼感知的是连续线性的运动,这其实是归功于运动模糊的效果。24fps是电影胶圈通常使用的帧率,因为这个帧率已经足够支撑大部分电影画面需要表达的内容,同时能够最大的减少费用支出。但是低于30fps是无法顺畅表现绚丽的画面内容的,此时就需要用到60fps来达到想要的效果,当然超过60fps是没有必要的。
开发app的性能目标就是保持60fps,这意味着每一帧你只有16ms=1000/60的时间来处理所有的任务。
我们如何来获得应用的帧率呢?线下环境我们可以使用Systrace等工具来进行分析,或者也可以使用GPU呈现模式分析来检测丢帧卡顿等问题。现在,如果我们想要监控线上用户的在使用过程中,是否卡顿丢帧,想要知道APP真实环境的帧率是多少?如何来做呢?
线上帧率监控实现
想要实现线上用户的帧率监控,我们可以通过 Choreographer.FrameCallback 回调来实现帧率监控。
关于 Choreographer 的实现原理,请参考《从源码分析Choreographer是如何实现VSYNC信号的请求及帧的刷新处理?》。
package com.budaye.simpledemo;
import android.util.Log;
import android.view.Choreographer;
/**
* @ProjectName: SimpleDemo
* @Desc:
* @Author: buyuntao
* @Date: 2020/11/11
*/
public class FpsTest implements Choreographer.FrameCallback {
private long mLastFrameTimeNanos = 0; //最后一次时间
private long mFrameTimeNanos = 0; //本次的当前时间
private int mFpsCount = 0;
public void startFps() {
mLastFrameTimeNanos = System.nanoTime();
Choreographer.getInstance().postFrameCallback(this);
AsyncThreadTask.executeDelayed(runnable, 1000);
}
//定时任务
private Runnable runnable = new Runnable() {
@Override
public void run() {
calculateFPS();
AsyncThreadTask.executeDelayed(runnable, 1000);
}
};
private void calculateFPS() {
if (mLastFrameTimeNanos == 0) {
mLastFrameTimeNanos = mFrameTimeNanos;
return;
}
float costTime = (float) (mFrameTimeNanos - mLastFrameTimeNanos) / 1000000000.0F;//纳秒转成毫秒。
if (mFpsCount <= 0 && costTime <= 0.0F) {
return;
}
int fpsResult = (int) (mFpsCount / costTime);
mLastFrameTimeNanos = mFrameTimeNanos;
mFpsCount = 0;
Log.d("budaye", "当前帧率为:" + fpsResult);
}
@Override
public void doFrame(long frameTimeNanos) {
mFpsCount++;
mFrameTimeNanos = frameTimeNanos;
//注册下一帧回调
Choreographer.getInstance().postFrameCallback(this);
}
}
-
使用线程,执行一个异步定时任务,每1000ms执行一次,用于统计1秒内的帧率。
-
使用 Choreographer.getInstance().postFrameCallback(this) 注册 VSYNC 信号回调监听,当 VSYNC 信号返回时,会执行 doFrame 回调函数。
-
在 doFrame 方法中,我们统计每秒内的执行次数,以及记录当前帧的时间,并注册一下次监听。
扩展:Android系统中的常用时间戳
在前文中,doFrame 参数返回的时间是纳秒,我们在计算中也涉及到了时间单位的转换。我们在开发中经常会遇到各种时间戳,那么在Android中,都有哪些时间戳呢?又有上面区别呢?
ps:喜欢,就点个赞吧????~
本文地址:https://blog.csdn.net/u011578734/article/details/109627596
上一篇: MySQL存储引擎InnoDB的体系架构
下一篇: Docker的详细使用