Notifications
Article
Profiler深挖-CPU面板(2)
Updated 8 months ago
589
1
CPU
CPU就是电脑的大脑它只认识0和1,给它一个2它都会无奈的回你一句"what is this!" - - ! 所以我们写的代码最终会编译成它所认识的指令和数据都是0和1组成的。如果我们给它的指令和数据越多,那么它自然就处理的慢了对吧。
在说下帧率,就是每秒显示的帧数,似乎不太好理解。我来说个通俗易懂的,CPU和GPU同时在跑(通常GPU跑的快,然后会等CPU),无论谁先跑完都会等对方结束,那么这一个周期的所消耗的时间就是一帧了。我们游戏要想玩的比较流畅至少要达到每秒40帧,最差的情况下也需要达到每秒30帧。如果一个游戏跑60帧的话,那么留给每一帧的时间是 1000 / 60 = 16.66毫秒。如果跑30帧的话留给每一帧的时间是 1000 / 30 = 33.33 毫秒。如果以30帧来计算,留给CPU每帧的时间只有33毫秒。有些游戏就光Camera.Render就占了30多毫秒,这种怎么才能优化到30帧呢?呵呵~
如下图所示,打开Profiler以后在Hierarchy右侧,可以看到每一帧CPU和GPU消耗的总毫秒数,由于Profiler不支持我电脑的显卡,所以我的GPU这一栏显示的时间是0毫秒。
还是上面这张图,CPU Usage面板中包含了CPU每个大类型的使用量。包括,Rendering(渲染)、Script(脚本)、Physics(物理)、Animation(动画)、GarbageCollector(垃圾收集器)、VSync(垂直同步)、Global illumination(全局光照)、UI(界面)、Other(其他)
1)Rendering 这里可能会有同学有疑问?渲染不是GPU干的吗?为什么会有CPU的开销?原因是这样的,GPU只是个硬件,它并不知道你要渲染啥,所以需要从CPU将参数渲染的东西传入GPU。传的东西越多,是不是越占带宽就会越慢,而且Unity还有动态合批的功能,都需要在CPU这里计算。引擎在提交GPU之前还需要做一些裁剪的功能,这都会耗时。下一篇在讲Render面板的时候在详细展开。
2)Scripts 脚本开销,这个参数非常重要,我们写的代码开销都可以在这里看到。配合上一篇我们提到的Deep Profiler 我们可以看到脚本开销的具体耗时时间。
3)physics 物理开销,一般游戏都可以不使用物理引擎。
4)Animation动画开销,同屏参数动画的数量、骨骼数量、蒙皮影响的节点都会产生开销,美术同学都需要关注。
5)GarbageCollector 垃圾收集器,C#会定期自动执行垃圾回收功能,释放无用的堆内存。举个例子,比如一个清洁工正在清理街道,街道上的垃圾越多那么他清理的时间务必就会越长。垃圾回收器也是一个道理,由于Unity2018及以下垃圾回收还是同步执行,所以垃圾越多收集时自然就会卡以下。Unity2019改成了异步回收,但是不管同步还是异步我们都需要减少垃圾的数量,后面章节会详细展开讨论。
6)VSync 垂直同步,GPU算完以后需要将显示数据丢在显存中,但是从显存中到显示器它并不是一个同步的过程,这取决于带宽。试想一下如果显示器还没显示完,此时就把显存中的数据改了,那么画面是不是就不是这一帧的了也就是撕裂?那么垂直同步说白了就是一个字“等”~ 对画面要求不高的就把他关闭了吧。
7)Global illumination 全局光照,和Render一样,虽然光照是要在GPU中计算,但是光源信息是要从CPU传进去的。
8)UI 界面的元素发现修改或者改变需要进行网格合并,就是每次需要生成一个新的Mesh,这样才能减少DC。网格合并完同样需要提交给CPU。关于UI部分后面会详细展开讨论。
9)Other 其他,就是以上都不是没地方放的耗时就放在这里了。
通常情况下Usage可能我们只想关心某几个参数,如下图所示,我们可以点击每个Usage左侧的小方框进行关闭,这样在Profiler面板的曲线图中就只会显示我们关心的参数了。
Okay~ CPU Usage 我们已经讲完,继续来看耗时部分。还是先来一段前面用过的代码。
public class NewBehaviourScript : MonoBehaviour { void Update() { A(); } void A() { B(); } void B() { for (int i = 0; i < 100; i++) { Debug.Log(i); } } }
如图所示,overview右侧包含Total (耗时总量百分比) Self(自身耗时百分比)Calls(调用次数) GC Alloc(堆内存分配)Time ms (耗时时间) Self ms(自身耗时时间。)
我们来进一步解释一下含义上图中选中的 NewBehaviourScript.Update()
1)Total 63.1% 表示这个函数以及子函数加起来的总耗时占CPU总耗时的63.1%
2)Self 1.0% 表示这个函数自身耗时(不包含子函数)占CPU总耗时的1.0% 通过观察上面代码不难看出这个方法自身只是个for循环,真正耗时的地方是Debug.Log
3)Calls 1 表示NewBehaviourScript.Update()这一帧调用次数为1次。 我们在看看下面的LogStringToConsole 的 Calls调用次数是100 这是因为NewBehaviourScript.Update()中我们做了一个100次的循环,所以Debug.Log就会被执行100次。
4)GC Alloc 1.2MB 表示这个函数以及子函数加起来的总堆内存分配占用1.2MB 由此可以Debug.Log是多占堆内存,游戏正式发布以后一定要把它干掉。
5)Time ms 30.74ms 表示这个函数以及子函数加起来的总耗时时间为30.74ms
6)Self ms 0.49ms 表示这个函数自身耗时(不包含子函数)时间 0.49ms 自身的耗时只是for循环的时间所带来的耗时。
上面我们展示一个脚本的耗时时间描述,如果同样的脚本挂在了多个地方改如何呢?
public class NewBehaviourScript : MonoBehaviour { public bool isEnabel = false; void Update() { if (isEnabel) { for (int i = 0; i < 100; i++) { Debug.Log(i); } } } }
如果我们将上述代码挂在2个不同的游戏对象中,isEnabel变量一个设置true另一个设置false.如下图所示,我们可以看到NewBehaviourScript.Update()的Calls次数已经是2了。 所以这里显示的Total Self GC Alloc Times ms Self ms 两个脚本加在一起的事件。
我们在试想一下,真实游戏中可不仅仅只有2个脚本,可能会有N个脚本,每个脚本的中有各种变量影响着执行的代码。为了能更清楚的看到每个脚本的耗时,所以我们可以选择Raw Hierarchy。点击上图中左上角Hierarchy的下拉框,选择Raw Hierarchy即可。
如下图所示,NewBehaviourScript.Update()出现了两个,每个的调用次数Calls 都是1,下面的总耗时时间是0因为是我们代码中有个bool变量控制是否开启for循环
现在又有一个新问题,如果脚本绑定的很多的情况下,我怎么确定到底是哪个脚本绑定的耗时呢?如下图所示,我们将脚本分别绑定在 游戏对象a 和游戏对象b上。右下角选择show related Objects就可以看到这个脚本到底被哪个游戏对象所依赖,并且还会包耗时时间以及GC的分配。
右上角还有一个show calls的功能,它就是把左边的父子关系展开的右边面板里了,其他都是完全一样的。
最后就是Time line功能了,即使我们打开了Raw Hierarchy,大家可以看看上面的截图,我们只能看到每一个NewBehaviourScript.Update()的耗时,但是我们依旧是无法查看每一个Debug.log的耗时情况。如果想进一步的查看就需要打开Timeline了。
如下图所示,每个Debug.log具体的耗时占用,以及堆内存分配都可以通过TimeLine看到。
大部分情况下Hierarchy 和Raw Hierarchy模式已经够我们查看性能了。但是它无法精准化的看每一块分配。原因是Unity内部是有多线程的,而且2018以后还开放了ECS & Job System 工作线程。它是一个并行的概念,比如渲染线程和主线程的耗时如果没有Timeline如何体现在Hierarchy和Raw Hierarchy模式中呢?
既然提到了多线程,这里我在补充一个坑。很多朋友都觉得有时候Unity的Profiler不太准,莫名其妙的某些函数耗时就非常的高。其实原因就是开启了多线程渲染,只有主线程和所有子线程都跑完这一帧才算结束,大家试想一下,如果主线程已经跑完,由于渲染线程还没有跑完,所以主线程要去等渲染线程。那么主线程等待渲染线程的这部分耗时,如果在Hierarchy 和Raw Hierarchy模式下Unity就会安排到碰巧执行的主线程函数里,所以莫名其妙的某些函数耗时就非常的高就是这个原因。 为了解决这个问题,我建议查看性能的时候最好把多线程渲染关了,这样看到的信息就更准确一些。
Okay~ CPU已经介绍完毕,下一篇我们将继续介绍其他性能面板窗口。
Tags:
宣雨松MOMO
程序员 - Programmer
10
Comments
wenweihang
6 months ago
加油,雨松老师😘😘😘
0