Unity3D中使用Profiler精确定位性能热点的优化技巧
来源:互联网 发布:linux查看程序进程号 编辑:程序博客网 时间:2024/06/05 06:41
简介
在使用Profiler定位代码的性能热点时,很多同学往往忽略Profiler的提供接口,当发现某个Update函数特别耗时时,没有有效的手段进一步定位热点出自该Update函数的哪一个模块或哪一段代码。
使用Profiler评估客户端性能时,推荐使用Profiler提供的性能采样接口,来更精确地分析定位客户端存在的性能问题。
举个例子说明精确定位的优势:
测试源代码:
using UnityEngine;using System.Collections;using System.Collections.Generic;public class TestProfiler : MonoBehaviour { int t = 10000; // 每帧Update都会进行校验和运行 void Update () { Check(t); // 校验 Run(); // 运行 } void Check(int n) { ProfilerSample.BeginSample("Check"); CheckA(); // 校验模块A ProfilerSample.BeginSample("Calculate b"); // 数值运算 int b = n - 100; if (b < 10) b = 10; ProfilerSample.EndSample(); CheckB(b); // 校验模块B ProfilerSample.EndSample(); } void CheckA() { ProfilerSample.BeginSample("CheckA"); Debug.Log("校验模块A"); ProfilerSample.EndSample(); } void CheckB(int loopCount) { ProfilerSample.BeginSample("CheckB(loopCount={0})", loopCount); Debug.Log("校验模块B"); ProfilerSample.BeginSample("new List<string>"); List<string> strList = new List<string>(); ProfilerSample.EndSample(); for (int i = 0; i < loopCount; ++i) { ProfilerSample.BeginSample("Add str to list"); string str = string.Format("CheckB:{0}", i); strList.Add(str); ProfilerSample.EndSample(); } Debug.Log(string.Format("list count: {0}", strList.Count)); ProfilerSample.EndSample(); } void Run() { ProfilerSample.BeginSample("Run"); Debug.Log("开始运行"); DoSomething(); ProfilerSample.EndSample(); } void DoSomething() { } void OnGUI() { GUILayout.BeginVertical(); if (GUILayout.Button("Enable/Disable ProfierSample.")) { ProfilerSample.EnableProfilerSample = !ProfilerSample.EnableProfilerSample; } if (GUILayout.Button("Enable/Disable Profier sting format.")) { ProfilerSample.EnableFormatStringOutput = !ProfilerSample.EnableFormatStringOutput; } }}
关闭和开启Profiler性能采样接口的对比截图:
如上图,使用性能采样接口,可以精确发现该Update的耗时热点在Check函数下CheckB函数中,主要由List.Add()导致,被调用了9900次。
使用Profiler.BeginSample、Profiler.EndSample配对,可以有效定位用户自己编写的代码的性能热点。
除此之外,我封装了一套自己的接口,代码在本文最后面。之所以封装一层,原因如下:
1、提供Profiler性能采样开关,可随时关闭
2、提供字符串格式化功能,可在Profiler中显示自定义的文本,方便定位问题(使用时需要谨慎,后文叙述)
关于格式化字符串
有时候光知道热点代码位置是不够的,还需要知道代码中变量数据。
例如处理网络协议的OnRecv函数,该函数会根据不同的协议号调用不同的委托函数。此时,我们就可以在Profiler窗口中输出协议号、或者委托的具体函数名,以方便我们定位具体热点。
慎用格式化字符串
如果在Update函数中使用格式化输出,很有可能该Update函数每隔一段时间就会出现一次GC.Alloc。但这可能不是由于Update的实际操作导致,而是由于使用性能采样时的格式化输出导致的。
需要注意格式化字符串本身会带来内存分配开销,使用格式化字符串采样接口时需考虑自身对代码带来的影响。
使用经验:
1、在可能的热点函数上插入性能采样代码,建议编译手机版本来分析结果。当然,在熟悉代码的前提下,可以方便使用PC测试分析GC Alloc等问题。原因如下:
1)PC性能相对太好,一些手机上的瓶颈函数在PC上几乎不耗时,导致无法准确分析;
2)一些代码,特别是插件代码,PC和手机的执行流程不同,PC分析的结果不能准确表明手机也是同样结果。
2、在插入性能采样代码时,特别留意函数中是否存在多个return的现象。这些return如果没有处理好,就有可能导致性能采样的Begin和End不匹配,导致Profiler显示的结果有误。
3、对于协程函数,BeginSample、EndSample之间注意不能存在yeild return null,否则可能导致Unity客户端卡死、手机卡死等现象。个人分析:Begin和End配对分析的是单帧结果,出现yeild return null代表该区间将会分两帧甚至多帧完成。
封装好的性能采样接口代码(ProfilerSample.cs):
0 0
- Unity3D中使用Profiler精确定位性能热点的优化技巧
- Unity3D中使用Profiler精确定位性能热点的优化技巧
- Unity3D中使用Profiler精确定位性能热点的优化技巧
- [Unity] 使用Profiler.BeginSample()定位性能热点
- [Unity] 使用Profiler.BeginSample()定位性能热点
- Unity3d开发性能优化-性能分析工具Profiler使用
- PL/SQL性能优化工具profiler的部署和使用
- app性能优化之Time Profiler工具的使用
- app性能优化之Time Profiler工具的使用
- Unity性能优化工具之Profiler的使用
- Unity3d常见性能优化技巧
- unity3d 常规性能优化技巧
- 【优化】Unity的Profiler性能分析
- Unity3D性能优化 - Update() 的使用
- Unity3D性能优化 - Update() 的使用
- Unity3D的优化性能
- unity3d的性能优化
- Unity3D-Unity Profiler性能分析器
- Adobe_Acrobat_XI_Io pdf (可编辑)+破解补丁 安装
- python 文件游标以及 re 中的 match,sub(具体示例)
- Android Wear SDK 中文 ---- 创建表盘服务 [Building a Watch Face Service]
- leetcode112题 题解 翻译 C语言版 Python版
- Spring @Conditional注解的使用
- Unity3D中使用Profiler精确定位性能热点的优化技巧
- 在命令行下进行Oracle用户解锁
- 南京理工大学第八届程序设计大赛
- 【01背包/母函数】HDU2079选课时间(题目已修改,注意读题)【用背包求解方案数】
- 【4.29安恒杯】writeup
- 一个简单登陆示例的MVC和MVP实现
- Oracle12c连接问题[ORA-28040]
- SpringMVC中使用Interceptor拦截器
- JDK动态代理模式