Unity 性能分析器 (Unity Profiler)
性能分析器记录应用程序性能的多个方面并显示相关信息。使用此信息可以做出有关应用程序中可能需要优化的事项的明智决策,并确认所做的优化是否产生预期结果。
默认情况下,性能分析器记录并保留游戏的最后 300 帧,并显示有关每一帧的详细信息。可以在 Preferences 窗口(菜单:File > Preferences)中增加其记录的帧数(至多 2,000 帧)。**注意:**如果将此设置增加到很大的帧数,则性能分析器的开销和内存使用量可能产生更大的性能影响。
可以检查脚本代码,以及应用程序如何使用某些资源(这可能会降低应用程序速度)。还可以比较应用程序在不同设备上的性能。性能分析器具有几个不同的性能分析器模块,这些模块可以添加到性能分析会话中,从而获取有关渲染、内存和音频等方面的更多信息。
Profiler 窗口布局
- A: 性能分析器模块。这是可以在应用程序中接受性能分析的所有模块的列表。使用此区域顶部的下拉菜单可以在窗口中添加和删除模块。
- B: 性能分析器控件。使用这些控件可以设置要从哪个设备进行性能分析以及 Unity 应该执行哪种性能分析,可以在帧之间进行导航,还可以开始记录数据。
- C: 帧图表。此区域包含性能分析器进行性能分析的每个模块的图表。首次打开性能分析器时,该区域为空白;开始对应用程序进行性能分析时,该区域中将填充信息。
- D: 模块详细信息面板。此窗口区域中的信息根据所选择的模块而异。例如,选择 CPU Usage Profiler 模块时,此区域包含详细的Timeline时间轴和切换到 Hierarchy 视图的选项。选择 Rendering Profiler 模块时,此区域显示调试信息列表。首次打开性能分析器时,该区域为空白;开始对应用程序进行性能分析时,该区域中将填充信息。
A性能分析器模块
Profiler 窗口的顶部被分为几个性能分析器模块,这些模块对游戏的特定方面进行性能分析。对应用程序进行性能分析时,Unity 在相应图表中显示与每个模块相关的数据。
CPU Usage 模块最能够体现应用程序在每帧中花费的时间。其他模块收集更具体的数据,有助于检查更具体的方面或监测应用程序的重要信息,例如内存消耗、渲染或音频统计信息。
每个模块都有自己的图表。选择模块时,模块详细信息面板将显示在窗口的底部,可用于检查该模块收集的详细数据。
性能分析器模块 | 功能 |
---|---|
CPU Usage | 概要显示应用程序在哪些方面花费最多时间(涉及物理、脚本、动画和垃圾收集等多个方面)。该模块包含有关应用程序的大量性能分析信息,您可以使用这些信息来决定进一步使用哪些其他模块来调查应用程序中的更具体问题。该模块始终处于激活状态(即使您将其关闭)。请参阅 CPU Usage Profiler 模块 |
GPU Usage | 显示与图形处理有关的信息。默认情况下,此模块处于非激活状态,因为它的开销较大。请参阅 GPU Usage Profiler 模块。 |
渲染 | 显示有关 Unity 如何在应用程序中渲染图形的信息,包括有关静态和动态批处理、SetPass 和 Draw 调用、三角形和顶点的信息。请参阅 Rendering Profiler 模块。 |
Memory | 显示有关 Unity 如何在应用程序中分配内存的信息。这尤其适合用于查看脚本分配 (GC.Alloc) 如何引起垃圾收集或者是应用程序的资源内存使用量随时间变化的趋势。请参阅 Memory Profiler 模块。 |
Audio | 显示应用程序中的音频相关信息,例如何时播放音频源以及播放的音频源数量、音频系统需要的 CPU 使用率以及 Unity 为其分配的内存量。请参阅 Audio Profiler 模块。 |
Video | 显示应用程序中的视频相关信息。请参阅 Video Profiler 模块。 |
Physics | 显示应用程序中物理引擎已进行的物理处理的相关信息。请参阅 Physics Profiler 模块。 |
Physics (2D) | 与 Physics Profiler 模块类似,此模块显示应用程序中物理引擎已进行的 2D 物理处理的相关信息。 |
Network Messages (已弃用) | 显示有关多玩家高级 API 发送或接收的较低级数据包和消息的信息。 **注意:**多玩家高级 API 已被弃用。 |
Network Operations (已弃用) | 显示有关多玩家高级 API 发送和接收的消息中含有哪些类型或操作的详细信息,例如已传输的 SyncVar 或命令的数量。 **注意:**多玩家高级 API 已被弃用。 |
UI | 显示有关 Unity 如何为应用程序处理 UI 批处理的信息,包括 Unity 为何以及如何对项目进行批处理。请参阅 UI Profiler 模块。 |
UI Details | 与 UI 模块类似,此模块的图表添加有关批处理和顶点计数的数据,以及标记(包含有关触发 UI 变化的用户输入事件的信息)。 |
Global Illumination | 显示有关 Unity 在应用程序中的全局光照 (Global Illumination) 光照子系统中花费的 CPU 资源的信息。请参阅 Global Illumination Profiler 窗口。 |
性能分析器模块开销
某些性能分析器模块具有大量的数据收集开销,例如 GPU、UI 和 Audio Profiler 模块。为了防止这些模块影响应用程序的性能,可以通过在 Profiler Module 下拉选单中取消选择这些模块来将它们停用。这样可从窗口删除模块,让性能分析器停止收集该模块的数据,并减少性能分析器的开销。
这不适用于 CPU Usage 模块,该模块始终会收集数据(即使该模块处于非激活状态),因为其他模块依赖这些数据。
要添加模块,请选择 Profiler Module 下拉选单,然后选择要激活的性能分析器。从下拉选单选择性能分析器模块后,这个模块开始收集数据,但是在非激活时段内不显示任何数据。
为了避免 GPU Profiler 模块的开销,默认情况下该模块处于非激活状态。GPU Profiler 模块必须在应用程序启动时处于激活状态,才能挂接到图形驱动程序。如果稍后添加,在大多数平台上均无效,并且性能分析器显示消息:"GPU profiling is not supported by the graphics card driver (or it was disabled because of driver bugs)"。
如果您指示性能分析器收集数据并通过 Profiler.logFile API 而不是通过 Profiler 窗口将数据发送到磁盘,您可以通过 Profiler.SetAreaEnabled() 来关闭性能分析器模块。
某些通过外部 IDE 来调试脚本的设置也可能产生开销。为了避免发生此开销并获得更准确的测量值,请禁用 Editor Attaching 设置(菜单:Preferences > External Tools)。同样,对构建播放器进行性能分析时,请打开 Build Settings 并禁用 Script Debugging 以避免发生此开销。
B性能分析器控件
性能分析器控件位于 Profiler 窗口顶部的工具栏中。使用这些控件可开始或停止记录性能分析器数据以及浏览分析的帧。
控件 | 功能 | |
---|---|---|
Attach to Player | 选择对应用程序进行性能分析时所在的目标。默认设置为 Playmode 。也可以选择 Editor 以对 Unity Editor 进行性能分析并显示 Editor 当前在使用的资源。 Unity 还自动检测网络上正在运行或通过 USB 连接的所有设备,并将这些设备显示在下拉选单中。单击下拉选单中的 Enter IP 可手动输入设备的 IP 地址,以便在该设备上对应用程序进行性能分析。有关更多信息,请参阅应用程序性能分析。 | |
Record | 启用此设置可以在运行应用程序时记录活跃模块的性能分析信息。如果未启用此按钮,则在运行应用程序时,性能分析器不会收集任何数据。 | |
Back arrow | 向后导航一帧。 | |
Forward arrow | 向前导航一帧。 | |
Current Frame | 单击 Current Frame 按钮时,帧指示线会跳到最后记录的帧,并且性能分析器进入 Current Frame 模式。性能分析器在此模式下收集数据时,它会停留在当前帧上并实时显示收集的数据。再次单击该按钮将退出 Current Frame 模式。 | |
Frame number | 指示当前在性能分析器中查看的帧的编号。 | |
Clear | 从 Profiler 窗口擦除所有数据。 | |
Clear on Play | 启用此设置后,下次单击 Player 窗口中的 Play 或连接到新的目标设备时,可从 Profiler 窗口擦除所有数据。 | |
Deep Profile | 启用此设置可对所有 C# 方法进行性能分析。启用此设置后,Unity 会将检测功能添加到所有 Mono 调用,然后便可以对脚本进行更详细的调查。请参阅深度性能分析。 | |
Call Stacks | 要记录用于脚本内存分配的调用栈,请单击此开关。启用此选项时,性能分析器记录的帧具有 GC.Alloc 样本中的信息;即使在 Deep Profile 未激活的情况下,完整调用栈上的这些样本也会导致托管脚本分配。有关更多信息,请参阅"CPU Usage Profiler 模块"页面的分配调用栈部分。 | |
Load | 将已保存的性能分析器数据加载到 Profiler 窗口中。还可以加载播放器通过 Profiler.logFile API 写出到文件的二进制性能分析数据。 按住 Shift 按钮并单击 Load 按钮可将文件内容附加到当前性能分析帧。 | |
Save | 将性能分析器数据保存到 Project 文件夹中的 .data 文件中。 | |
上下文菜单 | ||
Color Blind Mode | 启用此设置可使性能分析器在其图形中使用更高对比度的颜色。这样可以增强红绿色盲(例如绿色盲、红色盲或蓝色盲)用户的视觉感知度。 | |
Show stats for "current" frame | 默认情况下,选择 Current Frame 按钮并进入 Current Frame 模式时,帧指示线不会随当前帧统计信息显示相关注释。这是因为统计信息注释可能导致难以实时查看数据。要显示注释,请启用此设置。 | |
Preferences | 打开 Preferences 菜单以调整特定于性能分析器的属性。 |
为了保持低开销,Unity 仅每隔五帧重绘一次 Editor UI。这样会导致更新过程略有卡顿。
深度性能分析
通常,性能分析器仅对用 ProfilerMarker 显式包裹的代码时序进行性能分析。这包括从引擎原生代码到脚本代码的调用(例如 MonoBehaviour
的 Start
、Update
或类似方法)的第一个调用栈深度。
如果未向您自己的代码添加更显式的 ProfilerMarker
检测,您可以视为脚本代码的子样本的唯一其他样本是回调到 Unity API 中的样本(如果已对该 API 进行检测)。带有性能开销的大多数 API 调用都会经过检测。例如,通过 Camera.main
API 访问主摄像机的操作被注册为"FindMainCamera
"样本。
启用 Deep Profile 设置后,性能分析器会对脚本代码的每个部分进行性能分析,并记录所有函数调用,至少包括进入任何 Unity API 中的第一个调用栈深度。此信息可用于帮助您确定代码对应用程序性能的影响,但这会带来很大的开销。
对应用程序进行深度性能分析时,Unity 会将性能分析器检测功能注入到所有脚本方法中,从而记录所有函数调用。这有助于了解应用程序代码在哪些方面花费最多的时间。
深度性能分析是资源密集型操作,会耗用大量内存。因此,在进行性能分析时,应用程序运行速度显著降低。深度性能分析更适合用简单脚本编写的小游戏。如果使用的是复杂脚本代码,则应用程序可能根本无法使用深度性能分析。对于许多较大的应用程序,深度性能分析可能会使 Unity 耗尽内存。
如果遇到问题,导致性能分析器的太多样本存储在环形缓冲区(用于将样本流式传输到性能分析器)中,Unity 将显示一条错误消息。为了增加环形缓冲区的大小,可以调整进行性能分析的播放器的 Profiler.maxUsedMemory 属性。
如果深度性能分析导致应用程序的帧率下降太多而无法运行,您可以手动对脚本代码块进行性能分析,此方法的开销小于深度性能分析。使用 ProfilerMarker 可以手动添加标记脚本块所需的检测。这些会显示在 CPU Usage Profiler 模块中。
如果要找出产生 GC.Alloc 样本的调用栈而不想进行深度性能分析,可以开启__分配调用栈__的收集。启用性能分析器控件中的 Call Stacks 设置,然后可以在 Timeline 视图中选择 GC.Alloc 样本,或者使用 Hierarchy 视图中的 Show Related Objects 面板来查找这些样本的调用栈。
C性能分析器帧图表
Profiler 窗口的上半部分逐帧显示随时间推移的性能数据。运行应用程序时,性能分析器会记录每帧的数据。默认情况下,Profiler 窗口显示其进行性能分析的最近 300 帧的历史记录。可以在 Preferences 窗口中增加性能分析器进行性能分析的帧的数量(最多为 2,000 帧)。
在 Profiler 窗口的性能分析器帧图表区域中单击时,将出现一条白线来突出显示应用程序的一帧。要在帧之间导航,请使用 Profiler 窗口的工具栏中的传输控件。
Unity 自动管理图表的垂直刻度,而且图表会尝试填充窗口的垂直空间。要查看图表中的更多详细信息,可以删除其他性能分析器模块,也可以拖动图表和详细统计信息区域之间的分隔线来增大图表的屏幕区域。
要在图表中切换指标的隐藏和显示,请在相关模块中单击相应标签旁的有色方块。这样可以方便找到出现尖峰的原因。在堆积图表(例如 CPU Usage Profiler 的图表)中,可以将指标标签重新排序以影响堆积顺序。这样可以使干扰较多的指标更加明显,从而使图表更清晰。
每个性能分析器模块收集不同的性能数据指标并将它们显示在单独的图表中。单击某个帧时,Unity 在 Profiler 窗口下半部分的模块详细信息面板中显示有关该帧的更多详细信息。此窗口中的详细信息类型会因选择的性能分析器模块而异。有关每个模块在此区域中显示的特定详细信息的更多信息。
命令行参数
如果从命令行(例如 Windows 上的命令提示符,macOS 上的终端,Linux Shell,或者 Android 的 adb)启动构建的播放器或 Unity Editor,可以传递命令行参数来配置一些性能分析器设置。
命令行参数 | 描述 |
---|---|
-deepprofiling |
在构建的播放器中启用深度性能分析。 |
-profiler-enable |
对播放器或 Editor 的启动进行性能分析。将此参数与播放器一起使用时,效果与在 Build Settings 中启用 Autoconnect Profiler 选项来构建播放器的效果相同。 将此参数与 Editor 一起使用时,在 Editor 启动时会开始在 Profiler 窗口中收集和显示性能分析器信息。 |
-profiler-log-file <Path/To/Log/File.raw> |
此参数用于设置性能分析器,使其在启动时将性能分析数据流式传输到 .raw 文件。对播放器和 Editor 都有效。 |
-profiler-capture-frame-count <NumberOfFrames> |
此参数用于设置启动后流式传输到 .raw 文件时要在性能分析中捕获的帧数量。仅对播放器有效。 |
-profiler-maxusedmemory |
maxUsedMemory 的默认值是 16MB(对于播放器)和 256MB(对于 Editor)。可以在启动时使用此参数将 maxUsedMemory 参数设置为自定义大小(例如,-profiler-maxusedmemory 16777216 )。此大小以字节为单位。 |
D 模块详细信息面板( Hierarchy**)**
CPU Usage函数热点开销追踪
WaitForTargetFPS:Stats显示绘制能力:234FPS,真实绘制54FPS,对于游戏来说60FPS就够了,剩下的时间结余,可以休息。因此WaitForTargetFPS越高,休眠时间越多,越好。
Camera.Render:绘制摄像机的画面
Overhead:引擎没有统计到的未知开销
Animation.Update:采样出来某一帧的模型动画
BehaviourUpdate:所有脚本里的Update
- 如何获取方法中循环代码所消耗的时间,除了将它改写成一个方法外,还可以用这句代码解决
cs
Profiler.NeginSample("Test Input 10000");
for()
{
int i =0;
int x=i;
}
Profiler.EndSample();
Gui.Repaint:OnGui的一个开销,消耗极大
AudioManager.Update:声音播放的消耗
MeshSkinning.Update:蒙皮的消耗,这也是为啥stat里为啥要显示蒙皮的数量的原因
Cavas.RenderOverlays:与UGUI绘制相关的消耗
Graphics.Blit:摄像机后处理
什么是一个函数的开销:函数的开销=(调用一次函数消耗的时间:调用别人函数所占的时间+自己所占的时间)*调用次数
cs
test(){
Debug.Log("helloword");
int i=1000+1000;
}
追踪过程:谁Total高,谁作为优化的热点,Total是自己及其子物体所占的内存,Self是自己所占的内存。Calls是执行次数。
解决方案:减少调用时间(优化算法,优化结构),减少调用次数(减小问题的规模)
Rendering渲染热点开销追踪
优化Drawcall
算出哪儿些物体占的drawcall比较多,drawcall是怎么分布的
显示和隐藏场景文件中的游戏物体来查看是哪儿个游戏物体所占的drawcall较高
合批的数量也是有上限的,这也是为啥800个小兵是两个批次,而不是一个批次
优化思路
a:找到优化的热点
b:找到了以后再来想对策
今天是2024年11月20日
重复一段毒鸡汤来勉励我和你
你的对手在看书
你的仇人在磨刀
你的闺蜜在减肥
隔壁的老王在练腰
而你在干嘛?