【译】用Instruments进行调优
原文地址:http://blogs.unity3d.com/2016/02/01/profiling-with-instruments/
原文作者未做版权声明,视为共享知识产权进入公共领域,自动获得授权
在企业支持团队,我们见过很多IOS项目,在任何IOS项目开发过程中,总会出现这样的情况:开发者在运行他们游戏时候会想”到底为什么会运行这么慢?” 有很多很好的工具来进行性能调优,Instruments是其中最好的之一。继续阅读来学习如何使用。
要使用Instruments或者其他任何XCode的调试工具,你需要构建一个针对IOS的Unity工程。然后你需要用Xcode编出一个Release版本并把它部署到附着的IOS设备上。
在启动Instruments以后(或者通过点击Play按钮,或者选择Products>Profile),选择Time Profiler。为了进行一个调优,需要在应用选择选择刚才构建的应用,然后点击红色的Record按钮。然后应用就会在附着的iOS设备上启动,并与Instruments相连,Time Profiler会记录运行数据。
P.S.为了让调用堆栈比较干净好看,在右手边Call Tree的详细信息面板里面选择Flatten Recursion 和Hide System Libraries.。
一系列方法调用会出现Instruments窗口的详细信息里面,每一个顶层的方法调用都代表了一个线程。
总的来说,main方法是所有热点所在,因为他包含了所有受控方法。
展开main方法会得到一个很深的树形调用,主要是在这两个方法中:
- [startUnity] 和UnityLoadApplication (这些方法的名字可能会出现在每一个易用中).
- PlayerLoop
[startUnity]是用来初始化Unity的地方。在它里面会发现一个叫UnityLoadApplication的方法。 UnityLoadApplication 里面的启动时间是可以调优的
一旦你找到一个合适的时间切片,那就暂停Profiler,然后开始展开调用堆栈。当你随着调用树往下走的时候,你会注意到左侧的时间在减小,时间单位是ms。你应该注意那些时间急剧减少的地方。那将是一个性能热点。一旦你找到这样一个性能热点,你可以返回到你的代码分析到底是什么原因导致时间这么长。是否修正以及修正将取决于你,因为你比任何人都更了解这块代码。
Instruments也可以用来寻找散落在不同地方的小性能损失-并没有一个单独的大性能热点,但是可能在不同的地方重复出现很多次。为了找到他们,或者在Instruments的symbol search框输入完整或者部分函数名,这个搜索框位于调用树的右下方。如果调试的是一段游戏运行的代码,那么展开PlayerLoop然后折叠它内部的所有函数。如果调试的是启动阶段,那么展开UnityLoadApplication然后折叠它内部的所有函数。一个特定操作所花费的时间大致可以用花费的总时间减去它自身内部所花费的时间推算出来。
查找的通用方法:
l Box(“,“box” and “box”---这意味着发生了C#的值装箱。大部分这种情况是需要解决的
l Concat--- 字符串连接一般比较容易优化。
l CreateScriptingArray--- 所有返还数组的API都要分配一个新的数组,尽量减少对这样方法的调用。
l Reflection--- 反射很慢。尽可能得不要在运行时使用。
l FindObjectOfType– 用这个来定位重复的或者没必要的FindObjectOfType调用,或者其他已知很慢的Unity API。
l Ling--- 用这个来检查创建和丢弃Ling 查找所需要的时间。尽量不要使用。
除了对CPU时间调优,Instruments还允许你调优内存使用。Instruments内存分配优化器提供了两种探针来提供内存使用的详细视图。应用程序探针允许检查一段时间内内存中物体的存在情况。虚拟内存堆的探针可以监视堆的大小,这是iOS用来判断一个应用是否要被强制关掉的主要标准。
当打开Instruments里的Allocations profiler,两个探针会同时运行。和之前一样,按下红色的Record按钮就打开调优。
要设置对应用程序探针,需要在Instruments右手边的详细信息里面确保以下设置。在DisplaySettings里面,确保Allocation Lifespan设置为Created & Persistent。在Record Settings下面,确保Discard events for freed memory被选上。
对于监测内存行为最有用的信息展示是统计信息展示,默认使用的是应用程序探针。这个展示使用了一个时间轴。在推荐设置下,统计信息是一张随时间变化的内存使用量图。通过看这个图,你可以通过简单的重复来判断常驻内存有多大,是否有泄露。
另外一个有用的信息展示是Call Treee展示。它展示了内存具体在哪一行代码分配,以及具体分配了多少。
在下图中你可以看到光shader就占据了25%的内存。考虑到这个shader的位置是在加载线程中,可以推断这是Unity默认的标准shader,会在应用程序启动的时候进行加载。
像之前一样,一旦你确定了一个热点,你就需要返回你的工程里面去找到问题的答案。
企业支持团队正在写更多类似这样的指引,而且在接下来几个月我们会提交完整版的最佳实践!
当目标实现的时间,这种感觉很棒!