翻译自https://github.com/CyberAgentGameEntertainment/UnityPerformanceTuningBible/ 分析工具用于收集和分析数据,识别瓶颈,并确定性能指标。Unity引擎本身就提供了许多这样的工具。其他工具包括原生兼容的工具,如Xcode和Android Studio,以及特定于gpu的工具,如RenderDoc。
1.editor下用于快速验证修复 2.最后回归到真机验证
Unity Profiler是一个内置在Unity编辑器中的分析工具。这个工具可以逐帧收集信息。可以测量的项目范围很广,每个项目都称为分析器模块,在Unity 2020版本中有14个。这个模块仍在更新中,在Unity 2021.2中,增加了一个关于资产的新模块和一个关于文件I/O的新模块。Unity Profiler是一个很好的工具,可以粗略地查看性能,因为有各种各样的模块可用。
可以将这些模块配置为在分析器上显示或不显示。但是,没有显示的模块不会被测量。相反,如果全部显示,则编辑器将过载。
我们将分两部分解释测量方法,一部分在构建之前,另一部分在启动应用程序之后。
在构建开发构建之前要做的工作是启用“Development Build ”设置。一旦激活,就可以建立与分析器的连接。 此外,我们还需要启用Deep Profile选项以进行更详细的测量。当启用此选项时,将记录所有函数调用的处理时间,从而更容易识别瓶颈函数。缺点是测量本身需要非常大的开销,使其变得缓慢且占用大量内存。请注意,这个过程可能看起来需要很长时间,但在正常配置文件中并没有这么长时间。基本上,只有在正常配置文件不能提供足够的信息时才使用它。 代码中设置
BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions();
/* Scene and build target settings are omitted. */
buildPlayerOptions.options |= BuildOptions.Development;
// Add only if you want to enable Deep Profile mode
buildPlayerOptions.options |= BuildOptions.EnableDeepProfilingSupport;
BuildReport report = BuildPipeline.BuildPlayer(buildPlayerOptions);
GUI中设置
在应用程序启动后,有两种连接Unity Profiler的方法“远程连接”和“有线(USB)连接”。 这里主要讨论有线连接 首先,对于iOS,连接到分析器的过程如下。 1.将目标平台从构建设置更改为iOS 2.将设备连接到PC并启动Development Build应用程序 3.从Unity Profiler中选择要连接的设备(图3.5) 4.开始记录
接下来,Android的步骤要比iOS多一些。
adb forward tcp:34999 localabstract:Unity-jp.co.sample.app
https://blog.csdn.net/billcyj/article/details/81664215 【腾讯文档】UnityProfile连接安卓真机 https://docs.qq.com/doc/DWmxHYnRsQnhvaXRI
检查这个模块有两种主要方法 •层级(原始层级)Hierarchy (Raw Hierarchy) •时间轴Timeline 首先,根据Hierarchy视图所显示的内容以及如何使用它来解释它。
此视图的特点是测量结果以列表格式排列,并且可以按标题中的项进行排序。在进行调查时,可以通过打开列表中感兴趣的项目来识别瓶颈。 然而,所显示的信息表明所选线程所花费的时间。例如,如果您正在使用作业系统或多线程呈现,则不包括另一个线程中的处理时间。如果您想要检查,您可以通过选择如图3.8所示的线程来进行检查。
接下来,解释标题项。
调用更容易被视为视图,因为它将多个函数调用合并到单个项中。然而,尚不清楚它们是否都具有相同的处理时间,还是只有其中一个处理时间较长。 在这种情况下,Raw Hierarchy原始层次结构视图在本例中使用。Raw Hierarchy视图与Hierarchy视图的不同之处在于Calls总是固定为1。在下面的例子中,对同一个函数的多个调用显示在Raw Hierarchy视图中。
总结一下到目前为止所说的内容,Hierarchy视图用于以下目的 识别和优化瓶颈(Time ms, Self ms ) 识别和优化GC分配(GC Allocation) 在执行这些任务时,建议先对需要检查的项目进行降序排序,然后再进行检查。 Tips 当打开一个项目时,通常会有一个很深的层次结构。在这种情况下,您可以通过按住Mac上的Option键(Windows上的Alt键)打开层次结构的所有级别。相反,按住键关闭一个项目将关闭该层次结构下的所有内容
在时间轴视图中,层次视图中的项目显示为方框,因此在查看整个视图时,您可以直观地看到加载的位置。因为它是鼠标可访问的,即使是深层的层次结构也可以通过拖动来掌握。此外,有了时间线,就不需要切换线程;显示所有线程。这样就可以很容易地看到每个线程中什么时候发生了什么类型的处理。由于这些特性,时间轴主要用于以下目的 •获得整体处理负载的鸟瞰图 •了解和调优每个线程的处理负载 时间轴不适合排序操作以确定繁重处理的顺序,也不适合检查分配的总量。因此,HierarchyView 等级制度视图更适合调优分配。 补充:关于采样器 有两种方法可以测量每个函数的处理时间。一种是上面描述的Deep Profile模式。另一种方法是将其直接嵌入到脚本中。 在直接嵌入脚本的情况下,使用以下语句。
Profiler.BeginSample("Test Method")
TestMethod();
Profiler.EndSample()
嵌入的示例将同时显示在Hierarchy视图和Timeline视图中。
1.构建时未使用DevelopmentBuild,Profiler.BeginSample调用开销为0 2.在数学计算,多重for,update等频繁调用的地方使用Profiler.BeginSample BeginSample方法是一个静态函数,所以它可以很容易地使用,但是也有一个CustomSampler有类似的功能。在Unity 2017中有更少的测量开销比BeginSample,所以它可以测量更准确的时间。 CustomSampler
using UnityEngine.Profiling;
/* ... Omitted...*/
private CustomSampler _samplerTest = CustomSampler.Create("Test");
private void TestMethod()
{
for (int i = 0; i < 10000; i++)
{
Debug.Log("Test");
}
}
private void OnClickedButton()
{
_samplerTest.Begin();
TestMethod();
_samplerTest.End();
}
不同之处在于必须提前创建实例。CustomSampler的另一个特点是测量完成后可以在脚本中获得测量时间。如果需要更高的准确性或希望根据处理时间发出警告,CustomSampler是一个不错的选择。
有两种方法来检查这个模块 •简单视图Simple view •详细视图Detailed view
Total Used Memory Unity分配(正在使用)的内存总量。 Total Reserved Memory Unity当前保留的内存总量。操作系统预先预留一定数量的连续内存空间作为池,在需要时再分配。当池面积不足时,会再次向操作系统端请求扩容。 System Used Memory 应用程序使用的内存总量。该项还度量Total Reserved中未度量的项(插件等)。但是,它仍然不跟踪所有内存分配。为了得到一个准确的图像,你需要使用一个本地兼容的分析工具,比如Xcode。 右侧各数值含义
作为关于术语名称的额外说明,从Unity 2019.2开始, “Mono”已更改为“GC”,“FMOD”已更改为“Audio”。 资产分配内存 • Texture • Mesh • Material • Animation Clip • Audio Clip Asset Count 加载的资产总数 Game Object Count 场景中游戏对象的数量。 Scene Object Count 场景中组件和游戏对象的总数 Object Count 应用程序生成和加载的所有对象的总数。如果该值不断增加,则可能有某些对象正在泄漏。 GC Allocation in Frame 分配在一个帧中发生的次数和总量。 最后,此信息总结了Simple视图的用例。 •了解和监控堆面积和预留扩展时间 •检查各种资产和对象的泄漏 •监控GC分配 Tips Unity 2021及以后版本的Simple视图有了极大改进的UI,使其更容易看到显示的项目。内容本身没有大的变化,所以这里介绍的知识可以照旧使用。但是请注意,其中一些名称已经更改。例如,GC已被重命名Managed Heap 托管堆。
这个视图的结果可以通过点击“Take Sample”按钮来获取在那个时间点的内存快照的快照。与Simple视图不同,此视图不是实时更新的,因此如果您想刷新视图,则需要使用Take 样本。 在“Sample”按钮的右侧,有一个名为“reference By”的项。这将显示引用当前选定对象的对象。如果存在任何资产泄漏,对象引用的信息可能有助于解决问题。此显示仅在启用“收集对象引用”时显示。启用此功能将增加采样过程中的处理时间,但基本上建议保持启用状态。 在reference By中,您可以看到标记ManagedStaticReferences()。这意味着它被一些静态对象引用。如果您熟悉这个项目,这些信息可能足以给您一些想法。 每项的作用
分配给Unity使用的各种系统。 您可能不熟悉顶部节点中Others下面列出的项目。以下是你应该知道的项目列表。 System.ExecutableAndDlls程序集与dll 指示用于二进制文件、dll等的分配量。根据平台或终端的不同,它可能无法获得,在这种情况下,它被视为0B。项目的内存负载没有所列出的那么大的价值,因为它可以与使用公共框架的其他应用程序共享。与其急于降低这个项目,不如提高资产。要做到这一点,最有效的方法是减少dll和不必要的脚本。最简单的方法是改变剥离级别。但是,存在在运行时丢失类型和方法的风险 SerializedFile 序列化文件 指示元信息,例如AssetBundle中的对象表和作为类型信息的Type Tree。这可以通过AssetBundle发布。卸载(真或假)。Unload(false),它只在资产加载后释放这个元信息。请注意,如果发布时间和资源引用管理不仔细,资源可能会被双重加载,并且很容易发生内存泄漏。 PersistentManager.Remapper Remapper管理内存和磁盘上的对象之间的关系。 注意不要过度膨胀。特别是,如果加载了大量的assetbundle,映射区域将不够用,并且会被扩展。 因此,卸载不必要的AssetBundles以减少同时加载的文件数量是个好主意。此外,如果单个AssetBundle包含大量不需要的资产,那么将其拆分是一个好主意。 最后,我们将根据到目前为止所介绍的内容总结使用Detailed视图的情况。 •详细了解和调整内存在特定的时间 -检查不必要或意外的资产 •调查内存泄漏
Frame Debugger是一个工具,它允许您分析当前显示的屏幕是如何呈现的。该工具默认安装在编辑器中,可以通过选择“Window -> Analysis -> Frame Debugger”打开。 它可以在编辑器中使用,也可以在实际设备上使用。当在实际设备上使用它时,需要使用“Development Build”构建二进制文件,Unity Profiler也是如此。 启动应用程序,选择设备连接,按“使能”,显示绘图说明。
点击“Enable ”,显示如下画面。
左框显示了每个项目的单个绘图说明,说明是按照从上到下的顺序发布的。右框显示有关绘图说明的详细信息。你可以看到哪个着色器是用什么属性处理的。 在查看此屏幕时,请记住以下内容进行分析。 •是否有不必要的指令? •绘制批次(drawing batching )是否正常工作 •绘图目标的分辨率是否过高? •是否使用了非预期的着色器? Detailed Screen Operation Panel
当有多个渲染目标时,标记为“RT0”的部分可以更改。当使用多个呈现目标来检查每个目标的呈现状态时,这尤其有用。通道可以更改为显示所有RGBA或仅显示其中一个通道。级别是一个滑块,允许您调整结果渲染的亮度。这是有用的,例如,调整黑暗渲染的亮度,如环境或间接照明,使其更容易看到
此区域提供有关目的地的分辨率和格式的信息。显然,您将能够立即注意到是否有更高分辨率的绘图目标。其他信息,如使用的着色器名称,Pass设置(如Cull)和使用的关键字也可以找到。底部列出的句子“Why this~”描述了为什么不能批量绘制。在“Why this~”的情况下,它指出第一个绘图调用被选中,因此无法进行批处理。由于原因已经描述得如此详细,您可以信赖它
Detailed information on the Shader property 这个区域描述了正在绘制的着色器的属性信息。这对调试很有用
Tips 有时需要详细检查属性信息中显示的Texture2D状态。要做到这一点,请在按住图像的同时单击图像Mac上的命令键(Windows上的控制键)可以放大图像
译者增加部分 https://mp.weixin.qq.com/s/NV5Al4BVpEjxqBDtSOvLGg
内存分析器是Unity作为预览包提供的官方工具。与Unity Profiler的内存模块相比,它在以下几个主要方面是优越的。 •捕获的数据与截图一起保存在本地 •每个类别占用的内存量是可视化的,易于理解 •数据可以比较 内存分析器的UI在v0.4和更高版本之间发生了重大变化。本书使用v0.5,这是撰写本文时的最新版本。 对于v0.4及以上版本,需要Unity 2020.3.12f1及以上版本才能使用所有特性。
在Unity 2020中,你需要在“Project Settings ->Package Manager ”中启用“Enable Preview Packages ”。
然后在Unity中安装内存分析器。安装完成后,转到“Window -> Analysis -> Memory Profiler”启动该工具。
在Unity 2021及更高版本中,添加包的方法已更改。要添加一个包,点击“按名称添加包”并输入“com.unit .memoryprofiler”。
内存分析器由四个主要组件组成。 •工具栏Toolbar •快照面板Snapshot Panel •测量结果Measurement Results •细节面板Detail Panel 每个区域都给出了解释。 tool bar
Header的捕获。通过①按钮选择测量目标。按钮(2)测量按下时的内存。可选地,您可以选择仅测量本机对象或禁用屏幕截图。基本的默认设置应该没问题。点击按钮(③)将加载测量数据。点击“快照面板Snapshot Panel ”或“详细面板Detail Panel ”按钮将显示或隐藏屏幕左侧和右侧的信息面板。如果您只想看到树状图,最好隐藏它们。你也可以点击“?”打开官方文件。 关于测量,有一点需要注意。关于度量需要注意的一点是,度量所需的内存是新分配的,不会再次释放。然而,它不会无限增加,并将在几次测量后最终稳定下来。在测量时分配的内存数量将取决于项目的复杂性。如果您不知道这个假设,请小心,因为当您看到内存使用量膨胀时,您可能会错误地认为存在泄漏 Snapshot Panel
快照面板显示测量数据,并允许您选择要查看的数据。数据是按会话组织的,从应用程序启动到终止的时间。您还可以删除或重命名测量值通过右键单击数据。 “Single Snapshot 单个快照”和“Compare Snapshots 快照比较”在顶部可用。点击“Compare Snapshots 比较快照”将显示更改为比较测量数据的UI
“A”为“单快照”选择的数据,“B”为“比较”选择的数据快照。点击“替换”按钮,可以切换“A”和“B”,而不返回到单快照界面。 measurement results 测量结果有三个选项卡:“Summary”、“Objects and Allocations”和“Fragmentation”。本节介绍常用的“Summary”选项卡,并简要介绍其他选项卡作为补充信息。 Summary屏幕是一个名为Memory Usage Overview的区域,它显示当前内存的概述。控件中显示了一个解释详情面板,因此检查您不理解的项目是个好主意。
屏幕的下一个区域称为树图,它以图形方式显示每个对象类别的内存使用情况。通过选择每个类别,您可以检查类别内的对象。使用选择Texture2D类别。
屏幕底部的部分称为树图表。这里,对象列表以表格格式排列。可以通过按树图表的标题对显示的项目进行分组、排序和过滤。
特别是,将类型分组使其更容易分析,因此请主动使用它。
当在Tree Map中选择一个类别时,将自动设置筛选器以仅显示该类别中的对象
最后,当使用Compare Snapshots时,UI会发生变化。Memory UsageOverview 显示每个对象的差异。
在树映射表中,一个Diff项被添加到Header中。差异可以是以下类型
通过查看这些信息,可以检查内存是在增加还是在减少。
Detail Panel 当您想要跟踪所选对象的引用关系时,使用此面板。通过检查reference By,您将能够找出导致持续引用抓取的原因。
底部的部分Selection Details包含了该对象的详细信息。其中,“帮助”部分包含如何释放它的建议。如果你不确定该怎么做,你可以读一读。
补充:除摘要外的测量结果 “Objects and Allocations 对象和分配”与“Summary 摘要”的不同之处在于,可以以表格格式查看分配等更详细的信息。
“Fragmentation 碎片”显示虚拟内存状态,并可用于调查碎片。然而,它可能很难使用,因为它包含许多非直观的信息,如内存地址
一个名为“Memory Breakdowns 内存崩溃”的新功能从内存v0.6版开始添加分析器。需要Unity 2022.1或更高版本,但现在可以在列表视图和对象信息(如Unity子系统)中查看TreeMaps。其他新功能包括检查可能的重复对象的能力。
堆资源管理器是一个来自私人开发者Peter77 1的开源工具。如记忆该工具通常用于调查内存。 安装方法 复制GitHub存储库2中列出的包URL,并从添加包管理器中的Git url中的包。安装后,您可以从“窗口->分析->内存分析器”启动该工具。 *1 https://github.com/pschraut *2 https://github.com/pschraut/UnityHeapExplorer 如何使用 堆资源管理器的工具栏是这样的
左右箭头 允许您在操作中前后移动。这对于跟踪引用特别有用。 File文件 允许保存和加载测量文件。该文件以.heap扩展名保存。 View视图 切换不同的显示屏幕。有各种类型,所以如果你感兴趣,请参考文档 捕获 捕捉测量。但是,不能在堆资源管理器中更改测量目标。目标必须在Unity Profiler或Unity提供的其他工具中更改。Save将度量保存到一个文件并显示结果,而Analyze显示结果而不保存。注意,与Memory Profiler一样,在测量期间分配的内存不会被释放。
测量结果屏幕如下所示。这个屏幕叫做概述。
在概述中,特别关注的类别是Native Memory 本地内存使用和托管内存使用情况,用绿线表示。点击“Investigate调查”按钮查看每个类别的详细信息。 在下面的部分中,我们将重点关注类别细节的重要部分。
标题中有一些不熟悉的项。 DDoL DDoL代表“Don 't Destroy On Load”。您可以查看对象是否被指定为在场景转换后不会被破坏的对象。 Persistent 持续的 指示对象是否为持久对象。这是Unity在启动时自动创建的对象。 下面介绍的显示区域将通过选择对象Figure Referenced by 将显示引用目标对象的对象 左边子对象被谁引用
References to 显示目标对象引用的对象。 左边对象引用了哪些子对象右边
Path to Root 显示引用目标对象的根对象。这在调查内存泄漏时很有用,因为它允许您查看保存引用的是什么。
下面的图像总结了前面的项目。