Unity MemoryProfiler 的工作机制

转载:

https://gameinstitute.qq.com/community/detail/114030

 

Unity 的开源内存分析工具 MemoryProfiler 非常有用,可以提供所有由 Unity 分配的 C++ 对象的内存信息,在该工具内被称为 NativeUnityEngineObject (Native-only Mode)。当 C# 脚本经由 il2cpp 编译为 C++ 时,此工具可以提供额外的所有 C# 对象的信息,在该工具内被称为 ManagedObject (Full Mode)。

本篇文章简单地描述了Unity 的开源内存分析工具 MemoryProfiler的工作机制,并探讨了一下基于该工具的一些可能的改进,主要表现在以下这三个方面:

 

工作机制

 

这个工具中所能提供的所有的内存数据均来源于一个 Unity API:

UnityEditor.MemoryProfiler.MemorySnapshot.RequestNewSnapshot();

通过调用这个函数,我们可以向一个运行着的 Unity 程序请求一个新的内存快照。如果是运行于编辑器内的程序,该请求同步地返回上面说到的 Native-only Mode 数据;如果是运行于 iOS 上的基于 il2cpp 的应用,该请求异步地返回上面说到的 Full Mode 数据。

 

刚收到的快照存在于下面这个紧凑数据对象里:

 

public class PackedMemorySnapshot

{

    public Connection[] connections { get; }

    public PackedGCHandle[] gcHandles { get; }

    public MemorySection[] managedHeapSections { get; }

    public PackedNativeUnityEngineObject[] nativeObjects { get; }

    public PackedNativeType[] nativeTypes { get; }

    public TypeDescription[] typeDescriptions { get; }

    public VirtualMachineInformation virtualMachineInformation { get; }

}

 

收到这个紧凑数据对象后,MemoryProfiler 做了一些展开的工作,得到下面这个展开后的对象,内含完整的信息和交叉的引用:

 

public class CrawledMemorySnapshot

{

    public NativeUnityEngineObject[] nativeObjects;

    public GCHandle[] gcHandles;

    public ManagedObject[] managedObjects;

    public StaticFields[] staticFields;

    //contains concatenation of nativeObjects, gchandles, managedobjects and staticfields

    public ThingInMemory[] allObjects;

    public MemorySection[] managedHeap;

    public TypeDescription[] typeDescriptions;

    public PackedNativeType[] nativeTypes;

    public VirtualMachineInformation virtualMachineInformation;

}

 

这个过程中,最重要的是:所有的内存对象被展开到 ThingInMemory[] allObjects 这个多态数组里。有了所有的对象及它们间的引用关系,我们就可以做进一步的分类,调查和分析了。

 

 

实例类型

 

在上面的展开后的数据对象里,前四项值得分别说明一下:

1.  NativeUnityEngineObject[] nativeObjects 这是前面提到过的所有的 C++ 对象。我们无法看到这些对象的实际内容,但是可以看到下面这些信息:

    1)这是一个典型的 C++ 对象:

    2)在上图中,最有价值的信息有:

  • instanceID - 该对象的实例 ID,Unity 保证在一次运行期间新创建的对象不会与已销毁的对象复用 ID

  • References - 该对象引用的所有对象列表

  • Referenced by - 引用该对象的所有对象列表

 

2. ManagedObject[] managedObjects 这是所有的 C# 对象:

   1)由于该快照包含了对应的 managed heap 的信息,我们可以获得任意 C# 对象的数据细节。

   2)这是一个典型的 C# 对象:

   3)在上图中可以看到这个对象的每一个字段的详细内容。如果某个字段是对另一个对象的引用,可以直接点击跳转过去。

 

3. GCHandle[] gcHandles 用于 C#/C++ 对象的交叉生命期管理

   1)“If the native code will take ownership of that object, we need to tell the garbage          collector that the native code is now a root in its object graph. This works by using        a special managed object called a GCHandle.” 详见 IL2CPP Internals – Garbage         collector integration – Unity Blog

   2)简单地说,如果一个 C# 对象被一个 C++ 对象持有的话,一个 GCHandle 就会被创 建出来通知 GC 这种外部引用的情形存在

   3)通过任意一个 GCHandle 的 References/Referenced by 我们可以找到位于这个外部 引用两端的 C#/C++ 对象

 

4. StaticFields[] staticFields 则是所有的静态变量 (C#)

   1)这里你可以找到程序内现存的所有静态变量,是非常有用的功能。

   2)这是一个典型的静态变量:

  3)分析这些静态变量的数据可以发现,很多时候内存增长都是这种难以意识到的隐性的 静态容器的尺寸增长。

 

除了这些实例对象,还有 C# 堆的数据和其他一些类型信息,这里就不多说了。

 

 

可能的改进

 

以下是一些针对 MemoryProfiler 的一些可以改进之处。

层次化和结构化的数据展示改进:

  • 由于 MemoryProfiler 通过 Treemap 的形式展现数据,在操作时很容易因为数据量太大而难以定位到单个的对象。一个很容易得出的改进是使用更结构化的方式来归类和浏览不同类型的对象。实践中可以使用自制控件 TableView 来构造一个双层表格,分别用于类型和对象的展示。具体的使用例子可以参考文章 Unity 游戏的 string interning 优化

  • 这种表格的一个优势是可以自定义字段并显示对应的汇总统计信息

 

除了展示方式的改进之外,针对类型或实例的全文搜索,快照间的对比,分配时的细节诊断增强,都是非常有价值的潜在改进。在 ResourceTracker 中,可以看到我们基于开源的 Unity MemoryProfiler 做出的部分改进工作。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 作为一个 AI 语言模型,我认为如果你想在 Unity 领域找到工作,你需要掌握 C# 编程语言、Unity 引擎、游戏开发基础知识、3D 建模等技能。此外,了解游戏开发流程、团队协作、版本控制等也是非常重要的。希望我的回答能对你有所帮助。 ### 回答2: 要学习Unity工作,首先需要掌握Unity引擎的基础知识。这包括了解Unity的界面和工作流程,了解游戏开发的基本概念,例如场景控制、对象管理和脚本编写等。熟悉Unity的编辑器和各个功能模块,能够进行基本的场景构建和对象创建,掌握视觉和音频效果的实现。 其次,要学习编程语言,最常用的是C#。掌握C#编程语言的基本语法和面向对象编程的概念,能够编写脚本来实现游戏逻辑和交互效果。 此外,了解游戏开发的工作流程也是必要的。这包括了解项目管理和版本控制工具,例如Git,能够与团队成员进行良好的合作。 另外,学习如何使用Unity的开发工具和插件也很重要。Unity提供了丰富的资源和插件来加速开发进程,例如动画编辑器、物理引擎、UI编辑器等。熟悉这些工具的使用,能够高效地创建游戏内容。 最后,要通过实践来巩固所学知识。参与开发小项目或者加入游戏开发团队,亲身体验真实的开发过程,积累实际经验。 总的来说,Unity工作需要学习Unity引擎的基础知识,掌握C#编程语言,了解游戏开发工作流程和工具,以及通过实践来增强能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值