本文由博主(SunboyL)原创,转载请注明出处:http://www.cnblogs.com/xsln/p/BeginProfiler.html

简介

在使用Profiler定位代码的性能热点时,很多同学往往忽略Profiler的提供接口,当发现某个Update函数特别耗时时,没有有效的手段进一步定位热点出自该Update函数的哪一个模块或哪一段代码。

使用Profiler评估客户端性能时,推荐使用Profiler提供的性能采样接口,来更精确地分析定位客户端存在的性能问题。

 
    举个例子说明精确定位的优势:
    测试源代码:
 using UnityEngine;
using System.Collections;
using System.Collections.Generic; public class TestProfiler : MonoBehaviour {
int t = ; // 每帧Update都会进行校验和运行
void Update () {
Check(t); // 校验
Run(); // 运行
} void Check(int n) {
ProfilerSample.BeginSample("Check");
CheckA(); // 校验模块A ProfilerSample.BeginSample("Calculate b");
// 数值运算
int b = n - ;
if (b < )
b = ;
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 = ; 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):
 using UnityEngine;
using System; public class ProfilerSample { // by SunboyL
public static bool EnableProfilerSample = true;
public static bool EnableFormatStringOutput = true;// 是否允许BeginSample的代码段名字使用格式化字符串(格式化字符串本身会带来内存开销) public static void BeginSample(string name) {
#if ENABLE_PROFILER
if (EnableProfilerSample){
Profiler.BeginSample(name);
}
#endif
} public static void BeginSample(string formatName, params object[] args) {
#if ENABLE_PROFILER
if (EnableProfilerSample) {
// 必要时很有用,但string.Format本身会产生GC Alloc,需要慎用
if (EnableFormatStringOutput)
Profiler.BeginSample(string.Format(formatName, args));
else
Profiler.BeginSample(formatName);
}
#endif
} public static void EndSample() {
#if ENABLE_PROFILER
if (EnableProfilerSample) {
Profiler.EndSample();
}
#endif
}
}
 

Unity3D中使用Profiler精确定位性能热点的优化技巧的更多相关文章

  1. ASP.NET 性能监控工具和优化技巧

    转载自:http://blog.haoitsoft.com/index.php/archives/657 ASP.NET 性能监控工具和优化技巧 发表回复 为了阐明准确甄别性能问题的重要性,下面列举了 ...

  2. JVM 性能调优实战之:使用阿里开源工具 TProfiler 在海量业务代码中精确定位性能代码

    本文是<JVM 性能调优实战之:一次系统性能瓶颈的寻找过程> 的后续篇,该篇介绍了如何使用 JDK 自身提供的工具进行 JVM 调优将 TPS 由 2.5 提升到 20 (提升了 7 倍) ...

  3. 使用阿里开源工具 TProfiler 在海量业务代码中精确定位性能代码 (jvm性能调优)

    技术交流群:233513714 本文是<JVM 性能调优实战之:一次系统性能瓶颈的寻找过程> 的后续篇,该篇介绍了如何使用 JDK 自身提供的工具进行 JVM 调优将 TPS 由 2.5 ...

  4. ifeve.com 南方《JVM 性能调优实战之:使用阿里开源工具 TProfiler 在海量业务代码中精确定位性能代码》

    https://blog.csdn.net/defonds/article/details/52598018 多次拉取 JStack,发现很多线程处于这个状态:    at jrockit/vm/Al ...

  5. 15 个有用的 MySQL/MariaDB 性能调整和优化技巧(转载的一篇好文)

    MySQL 是一个强大的开源关系数据库管理系统(简称 RDBMS).它发布于 1995 年(20年前).它采用结构化查询语言(SQL),这可能是数据库内容管理中最流行的选择.最新的 MySQL 版本是 ...

  6. 【MySQL】15个有用的MySQL/MariaDB性能调整和优化技巧

    MySQL 是一个强大的开源关系数据库管理系统(简称 RDBMS).它发布于 1995 年(20年前).它采用结构化查询语言(SQL),这可能是数据库内容管理中最流行的选择.最新的 MySQL 版本是 ...

  7. 15 个有用的 MySQL/MariaDB 性能调整和优化技巧

    MySQL 是一个强大的开源关系数据库管理系统(简称 RDBMS).它发布于 1995 年(20年前).它采用结构化查询语言(SQL),这可能是数据库内容管理中最流行的选择.最新的 MySQL 版本是 ...

  8. NDK(20)JNI的5大性能缺陷及优化技巧

    转自 : http://www.ibm.com/developerworks/cn/java/j-jni/index.html JNI 编程缺陷可以分为两类: 性能:代码能执行所设计的功能,但运行缓慢 ...

  9. 提高Web性能的前端优化技巧总结

随机推荐

  1. DRBD架构详解(原创)

    DRBD概述Distributed Replicated Block Device(DRBD)是一种基于软件的,无共享,复制的存储解决方案,在服务器之间的对块设备(硬盘,分区,逻辑卷等)进行镜像.DR ...

  2. 配置React Native环境及解决运行异常

    一. 安装Homebrew: Homebrew的官网(多语言版本)简单明了地介绍了如何安装和使用这个工具,;并提供了自己的Wiki. brew的安装很简单,使用一条ruby命令即可,Mac系统上已经默 ...

  3. 向Windows内核驱动传递用户层定义的事件Event,并响应内核层的通知

    完整的程序在下载:http://download.csdn.net/detail/dijkstar/7913249 用户层创建的事件Event是一个Handle句柄,和内核中的创建的内核模式下的KEV ...

  4. 树莓派3b 串口通信初次尝试

    准备工作: 1. 安装wiringPi 2. 修改config.txt sudo nano /boot/config.txt 在文件的末尾添加: dtoverlay=pi3-miniuart-bt 3 ...

  5. java基础---->git的使用(一)

    这里面记录一下git的使用,只是平时工作中遇到的一些问题的解决方案,不会涉及到git的一些基础概念及说明.人的天性便是这般凉薄,只要拿更好的来换,一定舍得. Git的一些使用 一.在码云建立好仓库之后 ...

  6. 反编译获取线上任何微信小程序源码(转)

    看到人家上线的小程序的效果,纯靠推测,部分效果在绞尽脑汁后能做出大致的实现,但是有些细节,费劲全力都没能做出来.很想一窥源码?查看究竟?看看大厂的前端大神们是如何规避了小程序的各种奇葩的坑?那么赶紧来 ...

  7. Storm架构和编程模型总结

    1. 编程模型 DataSource:外部数据源 Spout:接受外部数据源的组件,将外部数据源转化成Storm内部的数据,以Tuple为基本的传输单元下发给Bolt Bolt:接受Spout发送的数 ...

  8. gcc6.3的安装

    author:headsen  chen date: 2018-10-12  15:11:35 1,环境:centos7.3 ,64位,内核 3.10 2,安装过程 #!/bin/bash yum i ...

  9. JDBC的驱动是如何加载的

    注:本文出处:http://www.cnblogs.com/jiaoyiping/ 转载请保留出处 JDBC定义了一套接口,数据库产品的提供商会实现这些接口来提供自己的数据库驱动程序,这是个很好的面向 ...

  10. MFC修改窗口无标题和标题信息,修改执执行文件图标

    一.创建MFC后 窗口显示的是 无标题-工程名 修改方法在网上看到了几种,下面介绍下比较简单的一种: 1.在MianFrame.c文件中找到这个函数 BOOL CMainFrame::PreCreat ...