• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

Unity Memory Profiler从入门到精通

武飞扬头像
金朝
帮助1

打开偏好设置:点击【Preferences -> Analysis -> MemoryProfiler】菜单项来打开偏好设置。如下图所示:
学新通
其中,常用的参数设置如下所示:
1.Memory Snapshot Storage Path:设置保存内存快照文件的相对路径(必须以./或者…/开头)。当路径非法时就会弹出错误提示,如下图所示:
学新通
2.Reset Opt-Out settings for dialog prompts:重置拍摄内存快照的提示框。该提示框内容如下图所示:
学新通
打开Unity Memory Profiler窗口:点击【Window > Analysis > Memory Profiler】菜单项来打开窗口。如下图所示:
学新通
工具栏区域:如下图所示:
学新通其中,常用的控件如下所示:
1.Attach To Player:用来设置捕获目标。该捕获目标可以是Unity Editor,也可以是运行在指定IP设备上的Development Build环境应用程序。如下图所示:
学新通
2.Capture:用来对捕获目标中指定的内存对象(托管堆对象-Managed Objects、本机堆对象-Native Objects、本机分配-Native Allocations)进行拍摄内存快照。当开始拍摄内存快照时,就会暂时冻结住捕获目标,具体冻结时间取决于应用程序的复杂性和内存的分配情况。当结束拍摄内存快照时,就会将内存快照显示到工作台区域。如下图所示:
学新通
3.Import:将内存快照文件导入到工作台区域。如下图所示:
学新通
除了上述导入方式之外,还可以采用工程目录导入方式,核心步骤为:首先在Unity工程目录下创建一个名称为MemoryCaptures的目录;然后将内存快照文件复制到MemoryCaptures目录中;最后打开Unity Memory Profile窗口,此时在工作台区域中就会同步显示MemoryCaptures目录下所有的内存快照文件。
4.View:设置查看内存快照的视图类型(树形视图-Tree Map、内存视图-Memory Map、差异内存视图-Memory Map Diff、表格视图-Table),如下图所示:
学新通
5.View history:使用箭头按钮在打开的历史视图之间来回切换。如下图所示:
学新通
6.Row Size:当View设置为[差异]内存视图类型时,此控件用来设置每行虚拟地址空间大小。如下图所示:
学新通
7.Display Filters:当View设置为[差异]内存视图类型时,此控件用来设置显示的数据类型([差异]本机分配对象-Allocations[Diff]、托管堆中的[差异]托管对象-ManagedObjects[Diff]、本地区域中的[差异]本地对象-NativeObjects[Diff]、虚拟内存区域中的保留地址空间-VirtualMemory、区域差异对象-RegionDiff)。如下图所示:
学新通
8.Color Scheme:当View设置为差异内存视图类型时,此控件用来设置虚拟内存的配色方案(常规配色-Normal、突出新分配内存配色-Allocated、突出释放内存配色-Deallocated)。如下图所示:
学新通
工作台区域:既可以显示所有的内存快照;又可以差异比对内存快照。如下图所示:
学新通
其中,该区域包含内容如下所示:
1.内存快照条目:包含屏幕截图、目标平台、名称、文件操作按钮、日期时间、开关按钮。如下图所示:
学新通
1.1.屏幕截图:当捕获目标为Unity Editor时,屏幕截图就为空。当捕获目标为Development Build环境应用程序时,屏幕截图就为捕获时的图片。
1.2.目标平台:显示项目工程对应平台(Mac、Windows、Linux、Android、iOS、WebGL等)的图标。
1.3.名称:显示内存快照的名称(默认为Snapshot-UTC时间前五位)。当鼠标停留在名称上时,就会弹出内存快照存储的绝对路径。
1.4.文件操作按钮:主要包含对内存文件进行删除、重命名、定位。当打开了内存文件时,不能进行删除和重命名内存文件。
1.5.日期时间:拍照时以UTC时间来存储内存快照文件,但是在显示时,就会自动转换成本机时间。当鼠标停留在日期时间上时,就会弹出内存快照来自于哪个项目工程。
1.6.开关按钮:用来在主视图区域中打开或者关闭内存快照。
2.已打开内存快照面板:包含打开的内存快照以及对两个打开的内存快照进行差异比对。如下图所示:
学新通
2.1.Swap按钮:用来交换打开内存快照的放置位置。默认情况下,新打开的内存快照会放置在左侧,最近旧的内存快照会放置在右侧。
2.2.Diff按钮:对两个打开的内存快照进行差异比对。此时Unity Memory Profiler首先会花费一些时间来生成差异数据;然后在主视图区域以Diff视图样式来显示差异数据。当主动关闭某一个打开的内存快照或者选择某一个打开的内存快照或者打开一个新的内存快照时,Unity Memory Profiler就会卸载差异数据,并在主视图区域以指定的视图样式来显示当前选择的内存快照的深度内存数据。

主视图区域:显示内存快照的深度内存数据。如下图所示:
学新通
其中,该区域包含内容如下所示:
1.树形视图:如下所示:
1.1.该视图会将内存数据分组到不同的对象类别下。
1.2.每个对象类别的大小就表示占用内存量大小。
1.3.当没有选择任何对象类别时,就会在Filters面板中显示所有对象类别当中的所有对象;否则就会在Filters面板中显示当前选择的对象类别中的所有对象。如下图所示:
学新通
2.[差异]内存视图:如下所示:
2.1.该视图会将内存数据可视化成虚拟内存布局。如下图所示:
学新通
2.2.每一行都会显示一个内存块和起始地址标签。当起始地址标签上面有黑色背景时,就表明该起始地址就是内存块的开始部分,并且与之前的内存块之间存在不连续性;否则,就表明该起始地址就是内存块的一部分。如下图所示:
学新通
2.3.既可以通过单击起始地址标签来选择关联的内存块;也可以通过单击鼠标拖动的方式来选择感兴趣的内存块;甚至可以通过单击内存块中的虚拟内存来选择该内存块。
2.4.当选择内存块时,就会在Filters面板中将相关的虚拟内存按照指定的列表类型(区域列表-Regions list、分配列表-Allocations list、对象列表-Objects list)进行展示详细信息。
区域列表类型展示信息如下图所示:
学新通
分配列表类型展示信息如下图所示:
学新通
对象列表类型展示信息如下图所示:
学新通
2.5.当视图为差异内存视图时,就会在Filters面板中显示New和Old两个按钮。通过这两个按钮进行动态切换不同的内存快照。如下图所示:
学新通
3.表格视图:如下所示:
3.1.该视图会以表格的形式来查看以下几种类型数据:
3.1.1.[Diff] Raw Data:从原始数据列表中选择一项原始数据(Root Reference、Native Allocation、Native Object等)进行查看。
3.1.2.[Diff] All Managed Objects:查看所有的托管对象(IL2CPP、Mono)。
3.1.3.[Diff] All Native Objects:查看所有继承自Unity.Object类型的本机对象。
3.1.4.[Diff] All Objects:查看所有本机对象和托管对象。
3.1.5.[Diff] Alloc:从分配列表中选择一项分配数据(ByNativeObject、ByRoot、ByMemRegion)进行查看。
3.2.该视图中包含的表格属性如下所示:
3.2.1.Index:对象列表当中对象条目的索引值。
3.2.2.Name:针对变量而言就显示名称,针对对象而言就显示地址。
3.2.3.Value:针对变量而言就显示数值,针对包含变量的对象就用蓝色来显示对象包含的变量信息,针对不包含变量的对象就显示地址。
3.2.4.Type:变量或者对象的类型。
3.2.5.Data Type:对象的类型(Managed Array、Managed Object、Native Object)。
3.2.6.Native Object Name:本机对象的名称。
3.2.7.Length:托管对象集合的长度。
3.2.8.Static:是否为静态。
3.2.9.RefCount:引用当前对象的其他对象总数。
3.2.10.Owned Size:针对托管引用而言就显示指针的大小,针对本机对象而言就显示对象大小,针对其他情况而言就显示0。
3.2.11.Target Size:针对托管引用和本机引用而言就显示被引用对象的大小,针对其他情况而言就显示0。
3.2.12.Native Size:本机对象的大小。
3.2.13.Native Instance ID:托管对象相关联的本机对象的唯一标识。
3.2.14.Address:对象在内存中的地址。
3.2.15.Unique String:用于比较对象的内部条目。
3.2.16.Diff:对象的比对状态(相同-Same、新增-New、删除-Delete)。
3.3.该视图中包含的表格排序如下所示:
3.3.1.Group:用一个三角箭头将指定列中具有相同值的对象组合在一起。通过点击该三角箭头来展开或者收起组内的对象。
3.3.2.Sort Ascending:将指定列中所有的对象按照数值从低到高进行排序。
3.3.3.Sort Descending:将指定列中所有对象按照数值从高到低进行排序。
3.3.4.Match:显示指定列中包含指定的匹配值的所有对象。

检测内存占用:可以使用Unity Memory Profiler来检测托管内存和本机内存的占用情况。检测流程如下所示:
1.首先打开Unity Memory Profiler窗口;然后打开想要检查的内存快照;最后在主视图区域以树形视图的方式来显示内存快照中深度内存数据。
2.查看树形视图中不同的对象类别。
3.单击树形视图中某一个对象类别,此时会展开该对象类别中所有的对象以及在主视图区域下方以对象表格的方式来显示该对象类别中所有的对象。
4.单击对象类别中某一个对象或者单击对象表格中某一个对象,进而可以在对象表格中查看该对象的具体信息。
5.首先将对象表格中所有的对象按照从高到低的顺序进行排序;然后优先从纹理、着色器变体、预分配缓冲区这三种对象来制定好减少内存的目标。

检测内存泄漏:可以使用Unity Memory Profiler来检测托管内存和本机内存的泄漏情况。如下所示:
1.出现内存泄漏的危害如下所示:
1.1.应用程序可能因为GC遍历对象时间变长的原因而出现卡顿现象。
1.2.应用程序可能因为可用内存空间不足的原因而出现闪退现象。
2.出现内存泄漏的原因如下所示:
2.1.对于自动垃圾回收而言,对象的引用计数不为0。
2.1.对于被动垃圾回收而言,对象没有被代码手动释放。
3.查找并修复场景卸载后发生的内存泄漏:流程如下所示:
3.1.使用Unity Memory Profiler来设置捕获目标。
3.2.首先在捕获目标上加载一个空场景;然后在该场景上拍摄一张内存快照。
3.3.首先在捕获目标上加载一个要检测内存泄漏的场景;然后在该场景上执行业务模块;最后将该场景卸载(调用Resources.UnloadUnusedAssets函数)掉或者切换到一个空场景。
3.4.在捕获目标上再拍摄一张内存快照。
3.5.为了避免处理内存快照文件和捕获目标之间竞争系统资源,建议此时关闭掉捕获目标。
3.6.首先在工作台区域打开第一张和第二张内存快照文件;然后单击Diff按钮来对两个打开的内存快照进行差异比对;最后将差异比对生成的数据显示在主视图区域中。
3.7.首先在主视图区域中选择Diff表格属性;然后选择Group排序规则来将相同值(Deleted、New、Same)的对象合并在一个组内;最后查看数值为New的分组,如果存在对象是在第二张内存快照中的话,就表明该对象的内存泄漏了。
4.查找并修复小的连续分配可能造成的内存泄漏:流程如下所示:
4.1.使用Unity Memory Profiler来设置捕获目标。
4.2.首先在捕获目标上加载一个要检测内存泄漏的场景;然后在该场景上拍摄第一张内存快照。
4.3.首先播放要检测内存泄漏的场景;接着在该场景上拍摄第二张内存快照;然后继续播放该场景;最后在该场景上拍摄第三张内存快照。
4.4.为了避免处理内存快照文件和捕获目标之间竞争系统资源,建议此时关闭掉捕获目标。
4.5.首先在工作台区域打开拍摄的第二张和第三张内存快照文件;然后单击Diff按钮来对两个打开的内存快照进行差异比对;最后将差异比对生成的数据显示在主视图区域中。
4.6.首先在主视图区域中选择Diff表格属性;然后选择Group排序规则来将相同值(Deleted、New、Same)的对象合并在一个组内。
4.7.首先在主视图中选择Owned Size表格属性;然后选择Group和Sort Descending排序规则来将相同值的对象合并在一个组内,并按照从大到小的顺序来排列组。
4.8.查看较大内存分配组中的对象是否同时存在于Same组和New组中,记录好满足条件的对象。
4.9.首先在工作台区域打开拍摄的第一张和第二张内存快照文件;接着单击Diff按钮来对两个打开的内存快照进行差异比对;然后将差异比对生成的数据显示在主视图区域中;最后执行4.6 ~ 4.8步骤,进而了解系统内潜在的内存泄漏。

元数据:如下所示:
1.元数据类型为MetaData,包含的字段如下所示:
1.1.content:包含项目名称和捕获目标为Unity Editor时的脚本版本。
1.2.platform:应用程序对应的目标平台。
1.3.screenshot:针对捕获目标截取的屏幕截图(像素大小小于480x240)。
2.首先在捕获目标上拍摄内存快照时就会生成元数据;然后该元数据会自动添加到内存快照中;最后开发人员可以通过元数据来更好地了解内存快照的内容。
3.拍摄内存快照的方式如下所示:
3.1.当项目中有安装Unity Memory Profiler时,此时就可以在工具栏区域中点击Capture控件来针对捕获目标来拍摄一张内存快照。
3.2.在代码中通过MemoryProfiler.TakeSnapshot/TakeTempSnapshot函数来针对捕获目标拍摄一张内存快照。在调用该函数时,可以设置包含内存快照文件路径字符串和是否拍摄成功布尔值两个参数的结束回调函数。
4.生成元数据的方式如下所示:
4.1.当项目中没有安装Unity Memory Profiler时,此时可以首先给MemoryProfiler.createMetaData委托注册一个监听函数;然后在该监听函数中设置元数据。
4.2.当项目中有安装Unity Memory Profiler时,此时就会生成默认的元数据。
4.3.当项目中有安装Unity Memory Profiler时,此时就可以首先创建一个继承自MetadataCollect类型的元数据收集类型;然后在该类型里面重写CollectMetadata函数;最后在该函数中设置元数据。

注意事项:如下所示:
1.给内存快照拍摄截图的功能只适用于Unity2019.3 。
2.虽然内存快照里面会包含捕获目标的全部托管堆内容,但是在Unity Memory Profiler窗口上面不会显示常量数据(内联到二进制中)。
3.无论项目处于哪种阶段,都要定期检查内存的使用情况,进而减少应用程序由于内存不足的原因而出现闪退。
4.由于内存快照文件占用磁盘空间比较大,所以在svn版本库中最好将.snap格式的内存快照文件忽略掉。

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhfkhbkf
系列文章
更多 icon
同类精品
更多 icon
继续加载