一只“性能狗“的自我修养——生动图解游戏性能神器 PerfDog
导读:玩家说"卡",可"卡"在哪里?
周五下午,体验群里炸了:
“新版本团战好卡!”
“我这边还好啊,60 帧稳稳的。”
“打了二十分钟手机烫得能煎蛋,然后就开始掉帧。”
“不是卡,是一顿一顿的,像踩到了坑。”
四句话,说的是四种完全不同的问题:帧率低、偶发卡顿、发热降频、帧耗时抖动。如果团队手里只有一句"玩家说卡",那么接下来的一周大概率是在猜。
这时候,大家会说:“先拿 PerfDog 跑一下。”
PerfDog(玩家和开发者常亲切地叫它"性能狗")是腾讯 WeTest 推出的移动及多平台性能测试工具。在国内游戏行业,它几乎成了性能数据的"普通话":研发拿它自测,QA 拿它验收,发行拿它和渠道、手机厂商对齐标准,甚至很多手机评测也会贴出它的曲线截图。
如果把一款游戏比作一个在高强度运动中的人,PerfDog 就像一台随身佩戴的运动监护仪:
| 监护仪上的读数 | PerfDog 上的指标 | 它告诉你什么 |
|---|---|---|
| 步频 | FPS(帧率) | 跑得快不快 |
| 心律不齐 | Jank / 卡顿 | 节奏有没有突然一顿 |
| 每一步的用时 | FTime(帧耗时) | 每一步是不是都均匀 |
| 心率 | CPU 占用 | 大脑和肌肉有多忙 |
| 肺活量占用 | GPU 占用 | 画面渲染有多吃力 |
| 胃里装了多少 | 内存 | 吃撑了没有,会不会"吐"(被系统杀掉) |
| 体温 | 温度 | 是不是在发烧 |
| 卡路里消耗 | 功耗 / 电流 | 耗电有多快 |
| 呼吸 | 网络上下行 | 和外界交换了多少数据 |
本篇的核心观点是:
PerfDog 的价值不在于"测出一个平均帧率",而在于用几乎零接入成本,在真实设备上同时、连续、可对比地记录游戏的帧、CPU、GPU、内存、温度与功耗曲线,让"玩家说卡"变成"在第几分钟、哪个场景、因为什么资源吃紧而卡"。它擅长告诉你"哪里疼、什么时候疼";至于"为什么疼",还要交给引擎分析器、系统级追踪与 GPU 抓帧工具去做手术。会用它的团队,会把它从一个"测试工具"变成一套"性能标准与回归体系"。
说明:PerfDog 的功能、支持平台、指标定义与授权方式会随版本更新,本文基于公开资料与常见使用经验撰写,具体以 WeTest / PerfDog 官网与官方文档为准。
一、它是谁:一只"不用打针"的狗
1. 出身与定位
PerfDog 由腾讯 WeTest 团队于 2019 年前后推出,最初主打移动端,后来逐步扩展到更多平台(官方介绍中包括 Android、iOS、HarmonyOS、PC 以及部分主机平台,以官网为准)。
它最打动开发者的,是三个"不用":
| 不用 | 意义 |
|---|---|
| 不用改游戏(无需集成 SDK) | 测竞品、测线上版本、测任意 App 都可以,不影响游戏代码 |
| 不用 Root / 越狱 | 普通量产手机即可测试,数据最接近真实玩家 |
| 不用改系统 | 不需要刷机、不需要特殊固件 |
用比喻说:别的体检方式需要"打针抽血"(往游戏里埋 SDK、改包),PerfDog 更像贴在手腕上的手环——贴上就测,摘下就走。
2. 它是怎么"听诊"的
PerfDog 主要借助操作系统本身提供的性能与调试能力采集数据:
| 平台 | 数据来自哪里(概念层面) |
|---|---|
| Android | 系统图形合成服务(如 SurfaceFlinger)的帧信息、/proc下的 CPU 与内存统计、系统电池与温度接口、GPU 驱动暴露的使用率等 |
| iOS | 苹果为开发工具提供的设备调试与性能服务(与 Xcode Instruments 使用的是同一类能力),因此无需越狱 |
| PC / 其他 | 对应平台的图形与系统性能接口 |
正因为它站在"系统视角"看游戏,它看到的帧,是真正被显示到屏幕上的帧——这比游戏自己在代码里统计的"逻辑帧率"更接近玩家眼睛看到的东西。
3. PerfDog 与 PerfSight:线下医生与线上体检
腾讯 WeTest 还有一个常被一起提起的产品 PerfSight:
| PerfDog | PerfSight | |
|---|---|---|
| 场景 | 线下测试:研发、QA、评测在特定设备上测 | 线上监控:玩家真实对局中的性能数据 |
| 接入 | 无需集成 SDK | 需要在游戏中集成 SDK |
| 数据规模 | 少量设备、精细曲线 | 海量设备、统计分布 |
| 比喻 | 诊室里的专科医生 | 全民体检数据中心 |
两者配合起来:线上数据告诉你"哪些机型、哪些场景的玩家最痛苦",线下 PerfDog 带你去那台手机上把问题复现出来。
二、为什么"平均帧率"会骗人
1. 一个经典的谎言
看下面两段 10 秒的录像,它们的平均帧率都是55 FPS:
录像 A:55 55 54 56 55 55 55 54 56 55 ← 均匀,玩家觉得"挺流畅" 录像 B:60 60 60 60 25 60 60 60 60 45 ← 平均也是 55,但玩家会说"一顿一顿的"平均数把"坑"填平了,可玩家的脚是会踩进坑里的。人眼对节奏的突然变化远比对整体帧率敏感:一直 30 帧的游戏可以玩得很舒服,但 60 帧里突然出现一个 150 毫秒的帧,就像走路时突然一脚踩空。
2. 帧耗时:把每一步都量一遍
所以 PerfDog 除了 FPS,还会记录FTime(每一帧的耗时)。如果说 FPS 是"每分钟走了多少步",FTime 就是"每一步各用了多少时间":
FTime(毫秒) 150 ┤ █ ← 一次大卡顿:玩家一定能感觉到 ┤ █ 83 ┤ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─█─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ← 两帧电影帧(约 83.3ms) ┤ █ 33 ┤ ▄ █ ▄ 16 ┤▄▄▄▄▄▄▄▄█▄▄▄▄▄▄▄▄▄▄▄█▄▄▄▄▄▄▄▄█▄▄▄▄▄▄▄▄▄ ← 理想的 60 帧:每帧约 16.7ms └──────────────────────────────────────▶ 时间3. PerfDog 的卡顿定义
为了让"卡"有一个可量化、跨团队一致的标准,PerfDog 定义了 Jank 与 BigJank(根据官方公开说明,具体以最新文档为准):
| 指标 | 判定条件 | 直觉理解 |
|---|---|---|
| Jank | 当前帧耗时 > 前三帧平均耗时的 2 倍,并且> 两帧电影帧耗时(1000/24 × 2 ≈ 83.33ms) | “比刚才明显慢了一倍,而且慢到人眼能察觉” |
| BigJank | 当前帧耗时 > 前三帧平均耗时的 2 倍,并且> 三帧电影帧耗时(≈ 125ms) | “严重卡顿,像画面冻住了一下” |
| Stutter(卡顿率) | 卡顿帧的耗时总和 / 测试总时长 | “这段时间里有多少比例是在卡” |
这个定义很聪明的地方在于两个条件缺一不可:
- 只看"比前几帧慢一倍":30 帧游戏中一个 40ms 的帧也会被误判,可人眼其实感觉不到;
- 只看"超过某个绝对值":一直 15 帧的游戏每帧都会被判卡顿,但这时问题是"整体太慢"而不是"突然一顿"。
相对突变 + 人眼可感知阈值,正好对应玩家说的"一顿一顿"。
我们可以用一段小脚本,把这个思想在自己导出的帧数据上复现一遍:
# 按 PerfDog 公开的思路计算 Jank / BigJank / 卡顿率(示意,用于理解指标,非官方实现)MOVIE_FRAME_MS=1000.0/24# 电影帧耗时约 41.67msdefanalyze_frames(ftimes_ms):jank=big_jank=0jank_time=0.0foriinrange(3,len(ftimes_ms)):cur=ftimes_ms[i]prev_avg=sum(ftimes_ms[i-3:i])/3sudden=cur>prev_avg*2ifsuddenandcur>MOVIE_FRAME_MS*3:big_jank+=1;jank+=1;jank_time+=cur# BigJank 同时也计为 Jankelifsuddenandcur>MOVIE_FRAME_MS*2:jank+=1;jank_time+=cur total=sum(ftimes_ms)return{"avg_fps":round(len(ftimes_ms)/(total/1000),1),"jank_per_10min":round(jank/(total/600000),1),"big_jank":big_jank,"stutter_pct":round(jank_time/total*100,2),}# 录像 B:大部分 16.7ms,夹杂两次长帧frames=[16.7]*300+[140]+[16.7]*300+[90]+[16.7]*300print(analyze_frames(frames))三、指标图鉴:监护仪上的每一根曲线
1. FPS 与帧稳定性:步频与步伐
| 关注点 | 怎么看 |
|---|---|
| 平均 FPS | 整体流畅度的第一印象 |
| FPS 方差 / 波动 | 曲线像平静的湖面还是心电图 |
| 低帧率时间占比 | 低于某个帧率(如 18 或 25 帧)的时间比例,反映"惨不忍睹"的时间有多长 |
| Jank / BigJank / 卡顿率 | 节奏突变 |
| 是否触顶 | 帧率稳稳贴在 60 / 90 / 120 的上限:说明还有余量,或被垂直同步、系统帧率策略限制 |
一个小提醒:帧率高不一定好。如果游戏只需要 30 帧却跑到了 60 帧,代价是耗电和发热翻倍——二十分钟后,手机就会替你"降温"。
2. CPU:大脑和肌肉
| 指标 | 含义 |
|---|---|
| 总 CPU 占用 / 应用 CPU 占用 | 整机和游戏各用了多少 |
| 各核心占用 | 是否某一个核被"压死"(游戏主线程或渲染线程常常是单核瓶颈) |
| CPU 频率 | 核心当前跑在多少 GHz;降频时频率曲线会"塌下去" |
| 线程 CPU(部分平台) | 哪个线程最忙:主线程、渲染线程、工作线程 |
这里有个常见的误会:“CPU 才用了 30%,怎么会是 CPU 瓶颈?”八核手机上,总占用 30% 可能意味着某一个大核已经 100% 满载,而其他核在休息——游戏主线程跑不动了,其他核再闲也帮不上忙。所以一定要看单核和频率。
3. GPU:画师的工作量
| 指标 | 含义 |
|---|---|
| GPU 占用率 | 画师有多忙;长时间接近满载,大概率是渲染瓶颈 |
| GPU 频率(部分平台) | 是否被降频 |
| iOS 上的 Renderer / Tiler 等 | 分别反映片元处理与几何(分块)阶段的负载,有助于区分是"像素太多"还是"顶点太多" |
判断瓶颈的经典口诀:
FPS 低 + GPU 接近满载 + CPU 单核不满 → 多半是 GPU 瓶颈(分辨率、过度绘制、后处理、着色器) FPS 低 + 某个 CPU 大核满载 + GPU 不满 → 多半是 CPU 瓶颈(逻辑、DrawCall 提交、物理、GC) FPS 低 + CPU、GPU 都不满 + 频率在下降 → 多半是发热降频或系统调度问题 FPS 低 + CPU、GPU 都不满 + 频率正常 → 可能在等:同步、I/O、加载、锁、垂直同步4. 内存:胃口与"呕吐"
| 平台 | 常见指标 |
|---|---|
| Android | PSS(按比例分摊的实际物理内存),以及细分项:Native、Java、Graphics(GL / GFX 显存相关)、未知等 |
| iOS | Memory(对应 Xcode 中看到的内存占用 footprint,最接近系统判断"吃撑"的依据)、Real Memory、Virtual Memory |
内存曲线有三种典型"体态":
健康:上下起伏,切场景后回落 /\/\/\/\ 泄漏:一路斜着往上,从不回头 ///////// → 迟早被系统杀掉 尖峰:平时还好,某个时刻突然冲高 ___/|\___ → 加载、解压、截图、大图集移动设备上内存超限的结果不是"变慢",而是闪退(Android 的低内存终止,iOS 的 Jetsam)。玩家只会说"游戏闪退了",而 PerfDog 的内存曲线会告诉你,它在闪退前的那一刻有多"撑"。
5. 温度与功耗:体温计和卡路里表
| 指标 | 含义 |
|---|---|
| CPU 温度 / 电池温度 | 手机有多烫 |
| 电流、电压、功率 | 每秒消耗多少电 |
| 电量 | 半小时掉了多少电 |
温度是性能里最"阴险"的变量,因为它有延迟:
时间(分钟) 0 5 10 15 20 25 30 温度 32℃ 38℃ 42℃ 44℃ 46℃ 46℃ 46℃ CPU 大核频率 2.8 2.8 2.8 2.4 1.9 1.8 1.8 GHz FPS 60 60 60 55 46 44 44前十分钟一切完美,测试报告写下"流畅";可玩家一局要打半小时。短时间测试永远发现不了发热降频,这也是为什么很多团队的性能标准里会要求"连续测试 30 分钟以上,并关注后半段数据"。
功耗还影响一个更现实的问题:玩家会不会因为"太费电、太烫"而放下手机。对手游来说,省电就是留存。
6. 网络:呼吸
上行、下行流量曲线可以帮助发现:同步数据是否异常增长、是否在不该下载的时候偷偷下载资源、语音开启后的流量变化等。对射击游戏而言,它也是第 52 篇网络同步优化效果的直观佐证。
四、上手:给手机戴上监护仪
1. 基本流程
1. PC 上安装 PerfDog 客户端(Windows / macOS),登录账号 2. 手机通过 USB 连接电脑 · Android:打开开发者选项与 USB 调试;首次连接时会在手机上安装辅助应用(用于悬浮窗等功能) · iOS:信任电脑即可,无需越狱 · 部分平台与版本支持 WiFi 无线连接,适合测功耗(避免 USB 充电干扰) 3. 在客户端选择设备 → 选择要测的应用(或具体进程) 4. 勾选要采集的指标(越多开销越大,按需选择) 5. 点击开始,去玩游戏 6. 过程中打标签、写批注、截图 7. 结束后保存,上传到 Web 平台做分析、对比与报告2. 三个让数据"会说话"的小动作
| 动作 | 作用 | 比喻 |
|---|---|---|
| 标签(Label) | 把时间轴切成段:大厅、加载、开局、团战、结算 | 在病历上写"上楼梯时"“跑步时”“休息时” |
| 批注 | 在某个时间点写一句话:“此处放大招”“此处进入烟雾” | 在心电图的异常处画个圈 |
| 截图 | 记录卡顿发生时的画面 | 拍下事故现场 |
没有标签的数据是一条长长的曲线;有了标签,它就变成了一份按场景拆开的体检报告:
| 场景 | 平均 FPS | Jank / 10min | 平均功耗 | 峰值内存 |
|---|---|---|---|---|
| 大厅 | 59.8 | 0.5 | 2.1 W | 1.6 GB |
| 加载 | — | — | 3.4 W | 2.3 GB |
| 对局前期 | 59.1 | 1.2 | 3.6 W | 2.0 GB |
| 决赛圈团战 | 47.3 | 9.6 | 4.8 W | 2.2 GB |
| 结算 | 58.5 | 3.0 | 2.6 W | 2.1 GB |
一眼就能看出:问题集中在"决赛圈团战"。而"结算"的 Jank 偏高,可能是结算界面加载资源或打包上报数据时的一次卡顿——这是另一个值得记下来的线索。
3. 让测试可重复
| 要素 | 建议 |
|---|---|
| 设备状态 | 电量相近、关闭后台应用、关闭省电模式与系统性能模式(或统一开启),屏幕亮度固定 |
| 环境温度 | 尽量一致;"冬天测得很好,夏天玩家喊烫"是经典事故 |
| 散热 | 不要放在散热器上测,也不要拿着手机一直吹空调;平放桌面或模拟手持 |
| 游戏设置 | 画质档位、帧率档位、分辨率、是否开启语音 |
| 测试路线 | 固定的关卡、固定的操作脚本,或使用回放与机器人对局(第 50 篇) |
| 时长 | 至少覆盖一局完整对局,发热相关测试 30 分钟以上 |
可重复,才可对比;可对比,数据才有意义。
五、读懂一份报告:一次"侦探故事"
新版本上线前,QA 报告:某款中端安卓机在决赛圈平均帧率从 55 掉到 42。研发拿到了 PerfDog 数据,开始破案。
第一条线索:FPS 曲线。不是一开始就低,而是在第 18 分钟左右开始逐渐下滑,伴随 Jank 增多。
第二条线索:温度与频率。第 15 分钟温度达到 45℃,大核频率从 2.4 GHz 降到 1.8 GHz。嫌疑人之一:发热降频。
第三条线索:CPU 单核。降频之后,一个大核长期 95% 以上——主线程在较低的频率下扛不住了。GPU 占用约 70%,不是瓶颈。
第四条线索:对比旧版本。在 Web 平台上把新旧两个版本的数据叠在一起:旧版本同一时间段的功耗低约 0.6 W,温度上升更慢。
推理:新版本的某项改动让整机功耗上升 → 更早触发降频 → 降频后主线程成为瓶颈 → 帧率下滑。
移交给"法医":PerfDog 只能告诉我们到这里了。接下来用引擎分析器(Unity Profiler / Unreal Insights)在同一台设备上抓取决赛圈的 CPU 帧数据,发现新版本加入的"决赛圈缩圈特效"每帧在主线程上更新了上千个粒子发射器的参数,还额外触发了一次全屏后处理。
结案与验证:粒子参数改为在 GPU 上计算、后处理按画质档位开关后,再跑一次 PerfDog——30 分钟后温度 43℃,频率保持在 2.2 GHz,决赛圈平均帧率回到 54,Jank 每十分钟从 9.6 降到 2.1。
这就是 PerfDog 在性能工作流中的位置:
玩家反馈 / 线上监控(PerfSight 等) ↓ 哪些机型、哪些场景 PerfDog:在真机上复现并量化 —— "哪里疼、什么时候疼、伴随什么症状" ↓ 锁定场景与资源瓶颈 专项工具:引擎分析器、系统追踪、GPU 抓帧 —— "为什么疼" ↓ 修复 PerfDog:同条件复测、新旧对比 —— "治好了吗,有没有副作用"六、四个典型"病例"
| 病例 | PerfDog 上的症状 | 常见病因 | 下一步工具 |
|---|---|---|---|
| 周期性小卡顿 | 每隔几十秒一个 Jank,CPU 短暂冲高,内存曲线呈锯齿状 | 托管堆垃圾回收(C#、Lua)、定时的大批量逻辑 | 引擎分析器的 GC 分配追踪;第 53 篇的零分配思路 |
| 首次出现某技能时卡一下 | 第一次释放时 BigJank,之后正常 | 着色器首次编译、资源首次加载、对象池未预热 | GPU 抓帧、着色器预热、资源加载日志 |
| 越玩越卡 | FPS 缓慢下滑,内存一路上涨,或温度上升伴随降频 | 内存泄漏、对象未回收、发热降频 | 内存快照对比;功耗分模块排查 |
| 画质越高越烫,帧率却不低 | FPS 达标,但功耗与温度显著高于竞品 | 渲染分辨率过高、帧率超出需要、后处理过重 | GPU 计数器工具;分档画质与帧率上限策略 |
还有一种"病例"值得单独提:竞品对比。由于 PerfDog 不需要集成 SDK,团队可以在同一台设备、同一环境下测试同品类的其他游戏,建立"行业水位"参照:在这台机器上,同类游戏一般跑多少帧、功耗多少、温度多少。这常常是制定自家性能标准的出发点。
七、让狗自己跑起来:自动化与回归
1. 为什么要自动化
人工测试有三个天然缺陷:慢、不稳定、不可持续。一个版本测 20 台机器、每台 30 分钟,就是 10 个小时,而且每次手速、路线都不一样。
PerfDog 提供了服务化与编程接口能力(官方称为 PerfDogService,通过 gRPC 等方式供脚本调用,提供多语言示例,具体能力以官方文档为准),可以与自动化测试框架配合:
每晚构建 → 安装到设备农场 → 自动化脚本启动游戏并运行固定路线(或机器人对局) → 通过接口启动 PerfDog 采集、按阶段打标签 → 采集结束上传 → 读取汇总数据,与基线对比 → 超出阈值则告警并附上曲线链接2. 一段示意代码
# 性能回归(示意):脚本流程与接口名称为概念性写法,实际请参照 PerfDogService 官方示例importtimedefrun_perf_case(perf,device_id,package,route,baseline,thresholds):perf.connect_device(device_id)perf.select_app(device_id,package)perf.enable_metrics(device_id,["fps","jank","frame_time","cpu","gpu","memory","temperature","power"])perf.start(device_id)forstageinroute:# 路线由自动化框架驱动游戏执行perf.set_label(device_id,stage.name)stage.run()# 例如:进入大厅 → 匹配 → 对局 → 决赛圈 → 结算summary=perf.stop_and_upload(device_id,case_name=f"{package}-{time.strftime('%Y%m%d')}")regressions=[]forlabel,minsummary.by_label.items():base=baseline.get(label)ifnotbase:continueifm.avg_fps<base.avg_fps*(1-thresholds["fps_drop"]):regressions.append((label,"avg_fps",base.avg_fps,m.avg_fps))ifm.jank_per_10min>base.jank_per_10min+thresholds["jank_increase"]:regressions.append((label,"jank",base.jank_per_10min,m.jank_per_10min))ifm.peak_memory_mb>base.peak_memory_mb*(1+thresholds["mem_increase"]):regressions.append((label,"peak_memory",base.peak_memory_mb,m.peak_memory_mb))ifm.avg_power_w>base.avg_power_w*(1+thresholds["power_increase"]):regressions.append((label,"power",base.avg_power_w,m.avg_power_w))returnsummary.report_url,regressions3. 自动化的注意事项
| 问题 | 建议 |
|---|---|
| 测试波动 | 同一用例每台设备跑多次,取中位数;阈值留出合理容差 |
| 设备状态漂移 | 设备农场需要统一的温度、电量与后台管理;定期重启 |
| 数据可追溯 | 每次结果关联构建号、提交、画质档位与设备信息 |
| 告警疲劳 | 只对持续性、超阈值的回归告警,并附上曲线与对比链接 |
八、从工具到标准:给性能"立规矩"
一只狗再聪明,也需要有人告诉它"什么叫健康"。成熟的团队会基于 PerfDog 数据建立一套性能标准:
1. 机型分档
| 档位 | 代表 | 目标(示例,需结合品类与竞品数据制定) |
|---|---|---|
| 高端 | 当年旗舰 | 高画质 60 帧(或 90 / 120 帧档位)稳定,30 分钟温度可控 |
| 中端 | 主流中端机 | 中画质 60 帧或稳定 30 帧,Jank 少 |
| 低端 | 两三年前的入门机 | 低画质稳定 30 帧,不闪退 |
2. 指标门槛
# 性能验收标准(示例):数值仅为示意,应由团队基于竞品水位与玩家数据确定standards:mid_tier:duration_minutes:30scenes:[lobby,match_early,final_circle,settlement]fps:avg_min:55# 目标 60 帧档位low_fps_ratio_max:2%# 低于 25 帧的时间占比jank:per_10min_max:3big_jank_per_10min_max:0.5memory:peak_max_mb:2200no_leak:"对局结束回到大厅后,内存回落至开局前 +100MB 以内"thermal:temp_max_c:45fps_drop_after_20min_max:10%# 后半段相对前半段的帧率下降power:avg_w_max:3.83. 让标准长在流程里
| 节点 | 做法 |
|---|---|
| 需求阶段 | 新特效、新系统给出性能预算(参考第 53 篇) |
| 开发自测 | 研发对改动涉及的场景跑 PerfDog 对比 |
| 每日 / 每周回归 | 设备农场自动化跑分,超阈值告警 |
| 版本验收 | QA 按标准出报告,不达标需要评审豁免 |
| 上线后 | 线上监控数据与线下标准互相校准 |
九、它不是万能的:知道狗的边界
1. 局限
| 局限 | 说明 |
|---|---|
| 只看"症状" | 它告诉你 CPU 忙、帧卡顿,但不会告诉你是哪一个函数、哪一个 DrawCall 导致的 |
| 采集本身有开销 | 开启大量指标、高频采集时会带来少量额外开销;对比测试时保持相同的采集配置 |
| 测功耗的干扰 | USB 连接可能伴随充电,影响功耗与温度;有条件时使用无线连接或官方推荐的功耗测试方式 |
| 设备差异 | 不同芯片、不同系统版本暴露的指标不同,例如部分机型拿不到 GPU 频率 |
| 不等于玩家全貌 | 线下几台设备无法代表线上数千种机型、网络与环境 |
2. 配套的"专科医生"
| 想知道 | 工具 |
|---|---|
| CPU 上哪个函数、哪个系统最耗时 | Unity Profiler、Unreal Insights、Xcode Instruments(Time Profiler)、Android Studio Profiler、Simpleperf |
| 线程调度、锁等待、系统级事件 | Perfetto / Systrace(Android)、Instruments 的系统追踪(iOS) |
| GPU 每一帧画了什么、每个 Pass 多贵 | RenderDoc、Xcode Metal 帧捕获与 GPU 计数器、Snapdragon Profiler(高通)、Arm Performance Studio / Mali 相关工具 |
| 内存里装了什么 | 引擎内存分析器、Instruments(Allocations / Leaks)、Android 内存快照 |
| 线上玩家的整体分布 | PerfSight 等线上性能监控、自建埋点(第 27 篇) |
一个形象的分工:PerfDog 是急诊科的分诊台,测体温、量血压、看心电图,判断是"发烧了"还是"心律不齐";确诊和手术,交给后面的专科。
十、踩坑与取舍
| 常见错误 | 后果 | 建议 |
|---|---|---|
| 只看平均 FPS | 漏掉卡顿 | 同时看帧耗时、Jank 与低帧率占比 |
| 只测 5 分钟 | 发现不了发热降频 | 关键场景连续测试 30 分钟以上,关注后半段 |
| 测试条件不统一 | 新旧版本数据无法对比 | 固定设备状态、环境温度、画质与路线 |
| 不打标签 | 一条长曲线,难以定位场景 | 按场景打标签,结果按标签汇总 |
| 只测旗舰机 | 主流玩家的体验无人关心 | 按机型分档覆盖,重点关注中低端 |
| 看到总 CPU 不高就排除 CPU 瓶颈 | 漏掉单核满载 | 看单核占用与频率 |
| 帧率越高越好 | 发热、耗电、后半段掉帧 | 按品类与机型设置合理的帧率上限 |
| 把 PerfDog 当作根因分析工具 | 停在"CPU 很忙"无法前进 | 配合引擎分析器与 GPU 抓帧 |
| 测功耗时连着 USB 充电 | 功耗与温度失真 | 使用推荐的功耗测试方式 |
| 数据只留在个人电脑上 | 无法对比和追溯 | 统一上传到平台,关联构建号与设备 |
| 人工测试撑全部回归 | 慢、不稳定、易遗漏 | 设备农场 + 自动化 + 基线告警 |
| 没有性能标准 | "卡不卡"靠争论 | 分档机型 + 量化门槛 + 流程节点 |
| 忽视竞品水位 | 标准过高或过低 | 同设备、同环境测试竞品作为参照 |
小结
- PerfDog 是一台给游戏佩戴的"运动监护仪":无需集成 SDK、无需 Root 或越狱,在真机上同时记录帧率、帧耗时、卡顿、CPU、GPU、内存、温度、功耗与网络,借助系统提供的性能接口获取最接近玩家所见的数据。
- 平均帧率会骗人:帧耗时揭示每一帧的节奏;Jank / BigJank 以"相对前三帧突增一倍 + 超过人眼可感知阈值"的双条件定义卡顿,卡顿率反映卡顿时长占比。
- 读懂指标:CPU 要看单核与频率,GPU 看占用与分阶段负载,内存看体态(健康起伏、泄漏斜坡、加载尖峰)与平台对应的口径,温度与功耗要看长时间趋势——发热降频是"迟到的性能杀手"。
- 用好工具:标签把曲线切成场景,批注与截图记录事故现场;固定设备状态、环境、画质与路线,让数据可重复、可对比。
- 在工作流中的位置:线上监控指出哪些机型与场景最痛,PerfDog 在真机上复现并量化症状,引擎分析器、系统追踪与 GPU 抓帧找到根因,修复后再用 PerfDog 同条件复测验证。
- 从工具到体系:借助服务化接口与设备农场实现自动化回归和基线告警,基于竞品水位与机型分档制定量化的性能标准,并把标准嵌入需求、开发、回归、验收与线上的每个节点。
- 知道边界:它擅长"哪里疼、什么时候疼",不负责"为什么疼";采集配置、USB 充电与设备差异都会影响数据,需要配合其他工具与线上数据形成完整视图。
思考题
你的射击游戏在某款中端机上,玩家反馈"开局很流畅,打到第二个圈之后越来越卡"。请设计一次 PerfDog 测试方案(设备状态、时长、标签划分、需要重点观察的指标),说明你会如何根据曲线区分"发热降频""内存泄漏"与"决赛圈内容过重"三种可能,并给出每种情况下交接给哪类专项工具继续分析。
请为你的团队制定一份三档机型的性能验收标准:每档的目标帧率、卡顿上限、峰值内存、温度与功耗门槛,以及"后半段帧率下降"的限制。说明这些数值如何参考竞品测试与线上玩家数据得出,并设计一条自动化回归流水线,在每日构建后发现性能回归。
某次优化后,PerfDog 显示平均帧率提升了 5 帧,但功耗上升了 15%,30 分钟后的温度高了 3℃。你会认为这次优化成功了吗?请从玩家体验(流畅度、发热、续航)、机型差异与长时间游玩的角度,说明你会如何评估并做出决策。
延伸阅读
| 资料 | 说明 |
|---|---|
| PerfDog 官网与官方文档(WeTest) | 安装使用、指标定义、Web 平台与 PerfDogService 自动化接口的最新说明 |
| 腾讯 WeTest 社区与技术文章 | 性能测试方法、卡顿指标、功耗与发热测试的实践分享 |
| PerfSight 官方介绍 | 线上性能监控与 PerfDog 的配合 |
| Android Developers:Perfetto、Android GPU Inspector、Simpleperf 文档 | Android 系统级与 CPU 层面的深入分析 |
| Apple Developer:Instruments、Metal 帧捕获与 GPU 计数器、MetricKit | iOS 上的根因分析与线上诊断 |
| Unity Profiler / Memory Profiler 文档;Unreal Insights 文档 | 引擎层面的 CPU、内存与渲染分析 |
| RenderDoc、Snapdragon Profiler、Arm Performance Studio | GPU 抓帧与移动 GPU 计数器分析 |
| 本系列第 27、50、53 篇 | 数据分析、玩法与机器人对局、FPS 性能优化 |
后记
回到周五下午那个吵成一团的体验群。
一周之后,群里贴出的不再是"好卡"“还好啊”,而是一张张带标签的曲线:哪台机器、哪个场景、第几分钟开始、伴随着什么样的温度与频率变化。争论消失了,取而代之的是一句"好,这个交给渲染组,那个交给逻辑组"。
这就是一只好"狗"最大的价值:**它不替你修好游戏,但它让每一次"卡"都有了名字、有了时间、有了证据。**而一个团队把"玩家说卡"翻译成"数据说哪里卡"的能力,往往就是流畅与卡顿之间那道看不见的分水岭。