安卓帧率获取

背景

  性能优化,经常用到一些指标,诸如帧率、功耗等。对于普通app来讲, 之前一直使用gfxinfo指令获取丢帧率。但是这个指令无法获取游戏的帧率,查阅资料,发现SurfaceFlinger可以获取游戏帧率。

帧率获取原理

  1. 获取当前focused layer
    指令:adb shell ‘dumpsys SurfaceFlinger | grep -i Explicit -A 30’
    这一步看到focused layer name可能会不全,有省略号。可使用下一步指令查看完整layer name。focused的图层会有*号标志。示例如下:
PS D:\work> adb shell 'dumpsys SurfaceFlinger | grep -i Explicit -A 30'Z |  Window Type |  Layer Class | Comp Type |  Transform |   Disp Frame (LTRB) |          Source Crop (LTRB) |     Frame Rate (Explicit) (Seamlessness) [Focused]
---------------------------------------------------------------------------------------------------------------------------------------------------------------SurfaceView[com.netease.l22.nearme.g[...]tyPlugin.AndroidPlugin](BLAST)#142209 |            0 |            2 |     DEVICE |          0 |    0    0 1080 2376 |    0.0    0.0 1080.0 2376.0 |                                              [*]
  1. 获取SurfaceFlinger的layer列表
    指令:adb shell ‘dumpsys SurfaceFlinger --list | grep xxx’
    经过上一步获取到的focused layer name部分字符串xxx过来匹配,过滤掉不相关的数据。
  2. 获取具体图层的帧信息
    指令:adb shell ‘dumpsys SurfaceFlinger --latency <layer_name>’
    terminal输出格式大致如下:
    共有128行。第一行是刷新率。剩余的数据127行,分为3列,分别是:
    desiredPresentTime:应用期望提交的时间
    actualPresentTime:实际提交的时间
    frameReadyTime:帧准备好的时间
    每个数字,代表一个帧的时间戳,单位是ns。计算帧率,使用第二列数据,通过数时间戳,可以确定1秒有多少帧。
> adb shell dumpsys SurfaceFlinger --latency "xxxxx"
16666666
59069638658663  59069678041684  59069654158298
59069653090955  59069695022100  59069670894236
59069671034444  59069711403455  59069687949861
59069688421840  59069728057361  59069704415121
59069705420850  59069744773350  59069720767830
59069719818975  59069761378975  59069737416007
59069736702673  59069778060955  59069754568663
59069753361528  59069794716007  59069770761632
59069768766371  59069811380486  59069787649600
......

帧率获取脚本

  通过上述原理,将计算逻辑封装成python脚本。计算原理如下:

import subprocess
import time
from threading import Threadnanoseconds_per_second = 1e9class SurfaceFlingerFPS():def __init__(self, view, ip):self.view = viewself.ip = ipself.refresh_period, self.base_timestamp, self.timestamps = self.__init_frame_data__(self.view)self.recent_timestamps = self.timestamps[-2]self.fps = 0def __init_frame_data__(self, view):# print('__init_frame_data__()')out = ''try:out = subprocess.check_output(['adb', '-s', self.ip, 'shell', 'dumpsys', 'SurfaceFlinger', '--latency-clear', view])except subprocess.CalledProcessError as e:print(e.output)out = out.decode('utf-8')if out.strip() != '':raise RuntimeError("Not supported.")time.sleep(0.1)(refresh_period, timestamps) = self.__frame_data__(view)base_timestamp = 0base_index = 0for timestamp in timestamps:if timestamp != 0:base_timestamp = timestampbreakbase_index += 1if base_timestamp == 0:raise RuntimeError("Initial frame collect failed")# print('refresh_period={} base_timestamp={}\ntimestamps=\n{}'.format(refresh_period, base_timestamp, str(timestamps[base_index:])))return (refresh_period, base_timestamp, timestamps[base_index:])def __frame_data__(self, view):out = subprocess.check_output(['adb', '-s', self.ip, 'shell', 'dumpsys', 'SurfaceFlinger', '--latency', view])out = out.decode('utf-8')results = out.splitlines()refresh_period = int(results[0]) / nanoseconds_per_secondtimestamps = []for line in results[1:]:fields = line.split()if len(fields) != 3:continue(start, submitting, submitted) = map(int, fields)if submitting == 0:continuetimestamp = submitting / nanoseconds_per_secondtimestamps.append(timestamp)return (refresh_period, timestamps)def collect_frame_data(self, view):if view is None:raise RuntimeError("Fail to get current SurfaceFlinger view")self.refresh_period, self.timestamps = self.__frame_data__(view)# print("\ncollect_frame_data()\ntimestamps=\n" + str(self.timestamps))time.sleep(1)self.refresh_period, tss = self.__frame_data__(view)# print("tss=\n" + str(tss))self.last_index = 0if self.timestamps:self.recent_timestamp = self.timestamps[-2]if self.recent_timestamp not in tss:self.recent_timestamp = self.timestamps[-3]self.last_index = tss.index(self.recent_timestamp)self.timestamps = self.timestamps[:-2] + tss[self.last_index:]# time.sleep(1)ajusted_timestamps = []for seconds in self.timestamps[:]:seconds -= self.base_timestampif seconds > 1e6:  # too large, just ignorecontinueajusted_timestamps.append(seconds)# print('ajusted_timestamps=\n' + str(ajusted_timestamps))from_time = ajusted_timestamps[-1] - 1.0fps_count = 0for seconds in ajusted_timestamps:if seconds > from_time:fps_count += 1self.fps = fps_countdef start(self):th = Thread(target=self.collect_frame_data, args=(self.view,))th.start()def getFPS(self):self.collect_frame_data(self.view)return self.fps

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/65264.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Redis - Token JWT 概念解析及双token实现分布式session存储实战

Token 定义&#xff1a;令牌&#xff0c;访问资源接口&#xff08;API&#xff09;时所需要的资源凭证 一、Access Token 定义&#xff1a;访问资源接口&#xff08;API&#xff09;时所需要的资源凭证&#xff0c;存储在客户端 组成 组成部分说明uid用户唯一的身份标识time…

软体机器人研究报告:设计方法、材料与驱动、感知与控制

软体机器人因其出色的可变形性和高适应性受到了广泛关注&#xff0c;这些特性使其在医疗、救援、探测等复杂场景中展现出独特的优势和巨大的应用潜力。研究人员对软体机器人的设计方法、材料与驱动技术、感知与控制策略等方面进行深入研究&#xff0c;取得了一系列成果。 本文汇…

imgproxy图像处理的高效与安全

摘要 imgproxy作为一个高效且安全的独立服务器,为图像处理提供了全新的解决方案。它不仅简化了图像调整和转换的过程,还极大地提升了处理速度,确保了整个流程的安全性。通过集成imgproxy,用户可以轻松优化网页上的图像,提高加载速度,改善用户体验。本文将深入探讨imgpro…

获取XML 属性值

<controlActProcess classCode"CACT" moodCode"EVN"><queryByParameter><statusCode code"new"/><queryByParameterPayload><statusCode code"new"/><actId><value><!--申请单编号-->…

要查询 `user` 表中 `we_chat_subscribe` 和 `we_chat_union_id` 列不为空的用户数量

文章目录 1、we_chat_subscribe2、we_chat_union_id 1、we_chat_subscribe 要查询 user 表中 we_chat_subscribe 列不为空的用户数量&#xff0c;你可以使用以下 SQL 查询语句&#xff1a; SELECT COUNT(*) FROM user WHERE we_chat_subscribe IS NOT NULL;解释&#xff1a; …

RTMW:实时多人2D和3D 全人体姿态估计

单位&#xff1a;上海AI实验室 代码&#xff1a;mmpose/tree/main/projects/rtmpose 系列文章目录 RTMO: 面向高性能单阶段的实时多人姿态估计 目录 系列文章目录摘要一、背景二、相关工作2.1 自上而下的方法。2.2 坐标分类。2.3 3D Pose 3 实验方法3.1.1 任务限制3.1.3训练技…

操作系统之同步与互斥的基本概念

1. 同步的基本概念 定义&#xff1a;同步是指在多个并发执行的进程或线程之间协调其行为&#xff0c;以使它们能够正确地相互合作。在计算机科学中&#xff0c;同步通常指对共享资源进行访问控制&#xff0c;以避免竞争条件和死锁等问题。 实现方式&#xff1a;为了实现同步&a…

Lua元表

哈喽&#xff0c;好久没有做记录了&#xff0c;最近刚好有时间打算整理一些基础常用内容&#xff0c;先做一期关于Lua相关的内容热热身。如果内容有误&#xff0c;欢迎大家指出我会积极做出响应。 在Lua中&#xff0c;元表&#xff08;metatable&#xff09; 和 元方法&#xf…

香橙派5Plus启动报错bug: spinlock bad magic on cpu#6, systemd-udevd/443

一、问题 如图&#xff1a; 接上调试串口&#xff0c;每次启动都会报错。不过使用过程中没有发现有什么影响。 百度查阅&#xff0c;有一位博主提到&#xff0c;但是没有细说解决方案&#xff1a; spinlock变量没有初始化_spinlock bad magic on-CSDN博客https://blog.csdn.n…

多语言宿舍管理:宿舍管理系统的国际化

2.1 Java语言 Java语言是目前最流行的语言之一&#xff0c;不仅可以做桌面窗口形式的程序&#xff0c;还可以做浏览器访问的程序&#xff0c;目前最流行的就是用Java语言作为基础&#xff0c;做各种程序的后台处理。Java语言是操作变量的语言&#xff0c;而变量则是Java对于数据…

【Docker命令】如何使用`docker exec`在容器内执行命令

大家好&#xff0c;今天我们来聊聊Docker容器管理中的一个非常有用的命令&#xff1a;docker exec。在日常工作中&#xff0c;我们经常需要在运行中的Docker容器内执行各种命令&#xff0c;docker exec正是帮助我们实现这一需求的利器。下面我将通过一个简单的例子&#xff0c;…

FPGA自学之路:到底有多崎岖?

FPGA&#xff0c;即现场可编程门阵列&#xff0c;被誉为硬件世界的“瑞士军刀”&#xff0c;其灵活性和可编程性让无数开发者为之倾倒。但谈及FPGA的学习难度&#xff0c;不少人望而却步。那么&#xff0c;FPGA自学之路到底有多崎岖呢&#xff1f; 几座大山那么高&#xff1f;…

【KLEE】源码阅读笔记----KLEE执行流程

本文架构 1. 动机2.KLEE简介3.KLEE的代码工程结构4. 从KLEE主函数入手main函数step1: 初始化step2&#xff1a;加载.bc文件进行符号执行 读取测试用例输出日志信息 1. 动机 最近准备对KLEE进行修改使其符合我的需要&#xff0c;因此免不了需要对源码进行修改。读懂源码是对在其…

CS 144 check7: putting it all together

Exercises 经验&#xff1a;两边的TCP连接建立得尽快&#xff0c;如果服务器端启动了&#xff0c;客户端没有紧接着启动就连不上。 这是什么神奇的bug呢&#xff1f; 和我之前给域控刷SOC的版本一样。如果域控启动了&#xff0c;在我本地的电脑没有马上和域控的SOC通上信&…

2024年12月CCF-GESP编程能力等级认证Scratch图形化编程二级真题解析

本文收录于《Scratch等级认证CCF-GESP图形化真题解析》专栏,专栏总目录:点这里,订阅后可阅读专栏内所有文章。 一、单选题(共 10 题,每题 3 分,共 30 分) 第 1 题 2024 年 10 月 8 日,诺贝尔物理学奖“意外地”颁给了两位计算机科学家约翰霍普菲尔德(John J. Hopfie…

Suno Api V4模型无水印开发「综合实战开发自己的音乐网站」 —— 「Suno Api系列」第14篇

历史文章 Suno AI API接入 - 将AI音乐接入到自己的产品中&#xff0c;支持120并发任务 Suno Api V4模型无水印开发「灵感模式」 —— 「Suno Api系列」第1篇 Suno Api V4模型无水印开发「自定义模式」 —— 「Suno Api系列」第2篇 Suno Api V4模型无水印开发「AI生成歌词」…

服务器压力测试怎么做

在部署任何Web应用程序或服务之前&#xff0c;进行服务器压力测试&#xff08;也称为负载测试&#xff09;是确保系统能够处理预期用户流量的关键步骤。通过模拟大量并发请求&#xff0c;可以评估服务器的性能、稳定性和响应时间&#xff0c;识别潜在瓶颈&#xff0c;并优化资源…

PHP之伪协议

文章目录 PHP伪协议php://协议data://协议file://协议phar://协议zip:// & bzip2:// & zlib://协议 过滤器 题目练习[BJDCTF 2020]ZJCTF&#xff0c;不过如此BaseCTF[week1]Aura酱的礼物 PHP伪协议 file:// — 访问本地文件系统 http:// — 访问 HTTP(s) 网址 ftp:// …

linux驱动:6ull(4)初看设备树文件

目录 设备树存放路径 编译dts方法 属性 添加节点例子 在已经添加的节点上外加属性例子 linux内核匹配设备步骤 结合下面这个文章看 linux驱动&#xff1a;&#xff08;16&#xff09;在设备树添加自定义节点_linux设备树自定义字段-CSDN博客 设备树存放路径 在linux源码…

【物联网技术与应用】实验15:电位器传感器实验

实验15 电位器传感器实验 【实验介绍】 电位器可以帮助控制Arduino板上的LED闪烁的时间间隔。 【实验组件】 ● Arduino Uno主板* 1 ● 电位器模块* 1 ● USB电缆*1 ● 面包板* 1 ● 9V方型电池* 1 ● 跳线若干 【实验原理】 模拟电位器是模拟电子元件&#xff0c;模…