深入解析「卡顿帧堆栈」 | UWA GPM 2.0 技术细节与常见问题
在游戏开发过程中,卡顿问题一直是影响玩家体验的关键因素。UWA GPM 2.0全新推出的「卡顿帧堆栈」功能,专为研发团队提供精准、高效的卡顿分析方案,能够直观呈现游戏运行时的堆栈信息,助力团队迅速找到性能瓶颈。该功能一经上线,便引发了广泛关注,许多开发者提出了相关问题。下面,我们一一解答,看看是否有你关心的内容。
「卡顿帧堆栈」功能是否仅支持Unity引擎?
A:在Unity项目中,GPM SDK会自动对所有C#入口函数进行打点。自动打点支持由Unity Native层直接触发的C#函数,具体包括:
- 第三方插件或者项目自定义的MonoBehaviour的Update、LateUpdate、OnEnable等函数;
- 引擎C#入口函数,如URP的DoRenderLoop,UGUI的Canvas.SendWillRenderCanvases等;
- 引擎触发的C#回调函数,如MonoBehaviour的OnTriggerEnter、OnCollisionExit等。
主线程中任何的C#耗时都会被包含在以上的函数中;而对于引擎的Native堆栈,如 Camera.Render、Gfx.WaitForPresent等,暂不支持,这部分耗时会被记入「Others」中。
对于非Unity引擎的项目,研发团队可以通过GPM SDK提供的API手动打点,精确记录各个关键函数的执行耗时,实现相同的卡顿分析能力。
如何仅针对特定玩家采集「卡顿帧堆栈」信息?
A:你可以通过API自定义采集策略,决定是否开启「卡顿帧堆栈」功能,并根据项目需求灵活设定触发条件。例如,可以针对特定设备、特定用户群或特定场景动态启用数据采集,确保数据收集精准有效。
「卡顿帧堆栈」支持Lua代码的分析吗,还是仅限C#?
A:自动打点是支持C#的,Lua里面需要项目组自己调用GPM 2.0的API进行打点。可以参考SDK集成文档中的API “GpmSample.Push() / Pop()” 来进行操作。经过打点,无论是Lua、C++或者其他语言,都是可以支持的。
启用「卡顿帧堆栈」功能是否会影响游戏性能?
A:几乎不会产生额外性能开销。
原理:
- 打点API在创建GpmSample对象时,仅调用一次Native函数传递函数名字符串,在后续的Begin/End调用时,只需传递一个地址参数,开销极小;
- Unity中的自动打点采用了Native Hook的机制,同样具备极低的性能损耗。
验证:
UWA进行了详细的性能测试,对比了开启与关闭该功能时CPU耗时、利用率的变化,测试结果显示,该功能对游戏整体性能的影响可以忽略不计。具体的测试案例如下。
分别在正常场景(满帧)和压力场景(低帧)的环境下,进行1600次自动/API打点调用的测试,统计循环完成的耗时。
API测试代码如下,其中gpmApiSample为GpmSample类型。
int count = 0;for (int i = 0; i < 1600;i++){gpmApiSample.Push();count++;gpmApiSample.Pop();}
自动打点测试,在一个Prefab上挂1600个实现了OnEnable函数的Monobehaviour组件。测试时统计其SetActive(true)的耗时。
正常场景下,平均每次打点调用,耗时在0.5~2微秒(千次调用约0.5~2ms);
压力场景下,平均每次打点调用,耗时最高约4微秒(千次调用约4ms)。
以下是小米12上的测试数据。
正常场景下,单次调用增量,API调用均值<1微秒;自动打点均值<1微秒。
压力场景下,单次调用增量,API调用均值<1微秒;自动打点均值<2微秒。
从实际测试结果看,两类打点方式造成的额外开销也在同一个数量级。当然由于每款游戏都各不相同,开销也会有差异。
而在网络层面,则确实会带来一些网络传输量方面的开销。目前从我们接入的Case看下来,大约额外需要10KB/分钟的上行流量。但如果某一时刻的代码堆栈层数很深,内容很多,那么可能会再稍高一些。
为了控制性能和采集量,我们目前的堆栈功能在相邻的2个采集点之间也加入了最少10秒钟的间隔。后续我们可以开一些API出来,让大家可以自由指定数据回传的时机,在性能压力较低的场景下再将所有堆栈数据全部回传。
我能调整采集堆栈的深度吗?
A:卡顿帧堆栈功能打开时默认的堆栈深度为1层,在「GPM设置」-「阈值设置」下可以对调用帧采集的最大深度进行更改,支持设置1-20层之间的任意数值。一般来说20层堆栈已经足够定位出发生异常的函数堆栈,再者过深的堆栈采集也会导致开销变大,因此UWA在这边开放至最大20层的深度。
GPM 2.0「卡顿帧堆栈」功能为游戏研发团队提供了精准、直观的卡顿分析能力,让开发者能够快速锁定卡顿根因,优化游戏性能。无论是Unity还是其他游戏引擎,都可以通过自动或手动打点的方式,深入剖析各个环节的性能开销。如果你对游戏性能优化有更高要求,不妨试试GPM 2.0,让你的游戏体验更流畅!
关于GPM 2.0
GPM 2.0 是一款专为上线或测试阶段的游戏项目打造的高效性能监测工具。它不仅深入捕捉宏观性能数据,还通过其独特的性能无损截图功能,让开发者在不影响玩家体验的前提下,全面掌握玩家运行时的关键细节,从多个维度优化游戏的性能表现,提升整体用户体验。
如果您的项目也希望体验GPM 2.0的强大功能,欢迎随时与UWA取得联系。我们将为您提供免费试用机会,并在试用期间全程支持服务搭建、数据分析与反馈,确保您能够充分体验GPM 2.0带来的价值。
GPM 2.0新功能 集锦
《GPM 2.0 全新发布「卡顿帧堆栈」功能|精准高效定位游戏玩家端性能》
《GPM 2.0 重新定义性能监测与优化|从未知到已知,从被动到主动》
《UWA GPM 2.0 重新定义性能监测与优化|如何高效预警和定位玩家端的性能问题》
GPM 2.0案例精讲 集锦
《我们的目标是不耗电、不发烫、不闪退》
《冒险闯关类玩家关注的四大体验》
《玩家端性能数据 一手掌握》
《造成设备功耗高的罪魁祸首》
《海外市场设备适配性优化实战》
《5000人测试背后的秘密》
GPM 2.0实操篇 集锦
《GPM 2.0 实操之Session篇之如果闪退是因为内存崩了》
《GPM 2.0 应用场景实例之解决让人头疼的问题》
《GPM 2.0 助力设备监测、行为分析与性能优化|玩家共测新体验》
《GPM 2.0 API 功能助力定制你的性能优化》
《GPM 2.0 驱动优化与投放决策|硬件性能一目了然》
《GPM 2.0 多维数据与实时截帧完美结合》
相关文章:

深入解析「卡顿帧堆栈」 | UWA GPM 2.0 技术细节与常见问题
在游戏开发过程中,卡顿问题一直是影响玩家体验的关键因素。UWA GPM 2.0全新推出的「卡顿帧堆栈」功能,专为研发团队提供精准、高效的卡顿分析方案,能够直观呈现游戏运行时的堆栈信息,助力团队迅速找到性能瓶颈。该功能一经上线&am…...

推荐几款较好的开源成熟框架
一. 若依: 1. 官方网站:https://doc.ruoyi.vip/ruoyi/ 2. 若依SpringBootVueElement 的后台管理系统:https://gitee.com/y_project/RuoYi-Vue 3. 若依SpringBootVueElement 的后台管理系统:https://gitee.com/y_project/RuoYi-Cl…...
Mysql全文索引
引言 在MySQL 5.7.6之前,全文索引只支持英文全文索引,不支持中文全文索引,需要利用分词器把中文段落预处理拆分成单词,然后存入数据库。 从MySQL 5.7.6开始,MySQL内置了ngram全文解析器,用来支持中文、日文…...
配置终端代理
普通的魔法开启之后终端下git clone等命令仍然会无法使用,额外需要手动配置终端代理。 sudo vim /etc/apt/apt.conf.d/99proxyAcquire::http::Proxy "http://127.0.0.1:12334"; Acquire::https::Proxy "http://127.0.0.1:12334";在debian安装时…...

51单片机学习之旅——在LCD1602上显示时钟
新建工程 打开软件 LCD1602模块代码添加 因为我们在LCD1602上显示时钟,因此我们需要添加LCD1602的模块代码 跳转到这条博客51单片机学习之旅——模块化编程集_51单片机ruminant-CSDN博客,复制相关代码跳转到这条博客51单片机学习之旅——模块化编程集…...

Jest单元测试
由于格式和图片解析问题,可前往 阅读原文 前端自动化测试在提高代码质量、减少错误、提高团队协作和加速交付流程方面发挥着重要作用。它是现代软件开发中不可或缺的一部分,可以帮助开发团队构建可靠、高质量的应用程序 单元测试(Unit Testi…...
C++字符串处理指南:从基础操作到性能优化——基于std::string的全面解析
博主将从C标准库中的 std::string 出发,详细探讨字符串的处理方法,涵盖常见操作、性能优化和实际应用场景。以下内容将围绕std::string 的使用展开,结合代码示例进行说明。 一、std::string 的基本操作 1.1 创建与初始化 std::string 提供了…...

JVM类加载过程详解:从字节码到内存的蜕变之旅
一、类加载的意义与整体流程 在Java中,每一个.java文件经过编译都会生成.class字节码文件。但字节码本身并不能直接运行,必须通过 类加载(Class Loading)将其转化为JVM内存中的数据结构,才能被程序调用。 类加载过程就…...
【力扣Hot100详解】解锁“字母异位词分组”:用排序魔法一键通关力扣!
字母异位词分组,力扣第49题,看似是“找不同”的排列游戏,实则是哈希表与字符串处理的经典结合。这道题就像是一把钥匙,能帮你打开“如何高效归类数据”的算法大门。今天,我们就用 Java 带你用“排序魔法”轻松破解它&a…...

vite配置scss全局变量
vite配置scss全局变量 创建单独文件variable.scss在其中定义变量 vite.config.ts中配置 import { defineConfig } from vite import vue from vitejs/plugin-vue import path from path// https://vite.dev/config/ export default defineConfig({plugins: [vue()],resolve:…...
Spring Boot01(注解、)---java八股
Spring Boot中常用注解及其底层实现 1、SpringBootApplication注解: SpringBootApplication注解:这个注解标识了一个SpringBoot工程,它实际上是另外三个注解的组合,这三个注解是: aSpringBootConfiguration:…...

2.19学习记录
Web easyupload3.0 这是一道构造.htaccess文件的传马 如下: <FilesMatch "jpg">SetHandler application/x-httpd-php </FilesMatch>.htaccess文件可以作为一个解释器,可以将传进去的图片马改为php马上传之后再传个图片马&#…...

汽车免拆诊断案例 | 2013 款奔驰 S300L 车起步时车身明显抖动
故障现象 一辆2013款奔驰S300L车,搭载272 946发动机,累计行驶里程约为15万km。车主反映,将挡位置于D挡,稍微释放一点制动踏板,车辆蠕动时车身明显抖动,类似气缸失火时的抖动,又类似手动变速器…...

【HeadFirst系列之HeadFirst设计模式】第5天之工厂模式:比萨店的秘密武器,轻松搞定对象创建!
工厂模式:比萨店的秘密武器,轻松搞定对象创建! 大家好,今天我们来聊聊设计模式中的工厂模式。如果你曾经为对象的创建感到头疼,或者觉得代码中到处都是 new 关键字,那么工厂模式就是你的救星!本…...
Redis如何解决热Key问题
目录 **如何解决 Redis 的热 Key(Hot Key)问题?****解决方案** **1. 使用多级缓存****方案** **2. 进行 Key 预分片(Key Sharding)****方案** **3. 使用 Redis 复制机制(主从复制或集群)****方案…...

从开发到部署:EasyRTC嵌入式视频通话SDK如何简化实时音视频通信的集成与应用
嵌入式设备和视频综合管理平台均支持B/S架构。在B/S架构下,传统的视频观看方式依赖于微软的OCX控件,然而OCX控件的使用正面临越来越多的挑战: 首先,用户需要安装浏览器插件、调整浏览器安全级别,并允许ActiveX控件弹出…...
Zookeeper(58)如何在Zookeeper中实现分布式锁?
在 Zookeeper 中实现分布式锁是一种常见的用例。Zookeeper 提供了强一致性、高可用性的分布式协调服务,使得它非常适合用来实现分布式锁。以下是详细的步骤和代码示例,展示如何在 Zookeeper 中实现分布式锁。 1. Zookeeper 分布式锁的基本原理 Zookeep…...

Mac端homebrew安装配置
拷打了一下午o3-mini-high,不如这位博主的超强帖子,10分钟结束战斗 跟随该文章即可,2025/2/19亲测可行 mac 安装HomeBrew(100%成功)_mac安装homebrew-CSDN博客文章浏览阅读10w次,点赞258次,收藏837次。一直觉得自己写…...
Spring 接入 DeepSeek
引入依赖 <dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-openai-spring-boot-starter</artifactId> </dependency>2.yml配置 spring:ai:openai:api-key: sk-xxxxx // 填写自己申请的keybase-url: http…...
vscode将文件中行尾默认CRLF改为LF
安装prettier npm install --save-dev --save-exact prettier执行命令 npx prettier --write --end-of-line lf .即可将项目中的所有文件行尾序列格式改为lf *在你使用git拉取代码的时候,git会自动将代码当中与你当前系统不同的换行方式转化成你当前系统的换行方…...

springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...

深入理解JavaScript设计模式之单例模式
目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式(Singleton Pattern&#…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...

相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...

C++使用 new 来创建动态数组
问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...