Unity 内存管理和profiler详解

Unity Memory Management


Unity 的 Memory 构造


实际上Unity游戏使用的内存一共有三种:程序代码、托管堆(Managed Heap)以及本机堆(Native Heap)。

程序代码包括了所有的Unity引擎,使用的库,以及你所写的所有的游戏代码。在编译后,得到的运行文件将会被加载到设备中执行,并占用一定内存。 这部分内存实际上是没有办法去“管理”的,它们将在内存中从一开始到最后一直存在。一个空的Unity默认场景,什么代码都不放,在iOS设备上占用内存应该在17MB左右,而加上一些自己的代码很容易就飙到20MB左右。想要减少这部分内存的使用,能做的就是减少使用的库,稍后再说。

托管堆是被Mono使用的一部分内存。Mono项目一个开源的.net框架的一种实现,对于Unity开发,其实充当了基本类库的角色。 托管堆用来存放类的实例(比如用new生成的列表,实例中的各种声明的变量等)。“托管”的意思是Mono“应该”自动地改变堆的大小来适应你所需要的内存, 并且定时地使用垃圾回收(Garbage Collect)来释放已经不需要的内存。关键在于,有时候你会忘记清除对已经不需要再使用的内存的引用, 从而导致Mono认为这块内存一直有用,而无法回收。

最后,本机堆是Unity引擎进行申请和操作的地方,比如贴图,音效,关卡数据等。Unity使用了自己的一套内存管理机制来使这块内存具有和托管堆类似的功能。基本理念是,如果在这个关卡里需要某个资源,那么在需要时就加载,之后在没有任何引用时进行卸载。听起来很美好也和托管堆一样,但是由于Unity有一套自动加载和卸载资源的机制,让两者变得差别很大。自动加载资源可以为开发者省不少事儿,但是同时也意味着开发者失去了手动管理所有加载资源的权力,这非常容易导致大量的内存占用(贴图什么的你懂的),也是Unity给人留下“吃内存”印象的罪魁祸首。


iOS game profile


Unity has already created a basic guide on using Instruments to profile iOS games. It can be found here.
https://blogs.unity3d.com/cn/2016/02/01/profiling-with-instruments/


Unity 提供的 Profiler


进入Detialed,单击Take Sample: Editor可以看到以下几类内存数据

  • Assets: Asset referenced from user or native code (含有code里创建的game object)

  • Built-in Resources: Unity Editor resources or Unity default resources

  • Not Saved: GameObjects marked as DontSave

  • Scene Memory: GameObject and attached components (在当前scene里创建的game object)

  • When loading a new level all objects in the scene are destroyed, then the objects in the new level are loaded.

  • In order to preserve an object during level loading call DontDestroyOnLoad on it. If the object is a component or game object then its entire transform hierarchy will not be destroyed either.

  • Other: GameObjects not marked in the above categories 项目中通过代码生成的各种资源记录


Not Saved

Ref: http://blog.csdn.net/quan2008happy/article/details/39352535

DontSave:保留对象到新场景

功能说明:此属性的功能是用来设置是否将Object对象保留到新的场景(Scene)中,如果使用HideFlags.DontSave,则Object对象将在新场景中被保留下来,对其使用说明如下。

(1)如果GameObject对象被HideFlags.DontSave标识,则在新scene中GameObject的所有组件将被保留下来,但其子类GameObject对象不会被保留到新scene中。

(2)不可以对GameObject对象的某个组件如Transform进行HideFlags.DontSave标识,否则无效。

(3)即使程序已经退出,被HideFlags.DontSave标识的对象会一直存在于程序中,造成内存泄漏,对HideFlags.DontSave标识的对象在不需要或程序退出时需要使用DestroyImmediate手动销毁。

官方文档 https://docs.unity3d.com/ScriptReference/HideFlags.DontSave.html

The object will not be saved to the scene. It will not be destroyed when a new scene is loaded. It is a shortcut for HideFlags.DontSaveInBuild | HideFlags.DontSaveInEditor | HideFlags.DontUnloadUnusedAsset.

It is your responsibility to cleanup the object manually using DestroyImmediate, otherwise it will leak.


Other

  • 上面所提到的托管堆相关

    • ManagedHeap.UsedSize:托管堆使用大小(表示上次GC到目前为止所分配的堆内存量)。移动游戏建议不超过20M。
    • ManagedHeap.ReservedUnusedSize:托管堆预留不使用内存大小,只由Mono使用。
  • 我们值得关注的东西

    • SerializedFile: AssetBundle加载时产生的序列化信息,一般为LoadFromCacheOrDownload、LoadFromFile和New WWW加载本地AssetBundle文件所致,SerializedFile中记录的是AssetBundle的序列化信息,而不是其包含资源的内容,因此,其大小要小于或远小于资源的实际内存[^Zhihu]。实测SerializedFile所占的内存远小于bundle的实际内存,但是目前还是很容易上10M的。
      • 经过在Editor下实测,发现包括加载AssetBundle时产生的序列化信息,Editor导入资源时产生的Metadata的序列化信息,以及名为library/unity default resourcesresouces.asssets的两个文件。AssetBundle相关可以通过调用Unload(false)释放AssetBundle,从而释放对应的SerializedFile。Metadata相关在切换UI后会自动出现/消失,怀疑是在预加载UI这一类的。library/unity default resources也会不时消失,resouces.asssets似乎一直都在。不过值得欣慰的是这些不时出现的SerializedFile每个都在20K以内,而比较大的AssetBundle时产生的SerializedFile我们可以解决。
      • 在windows下实测,unload所有AssetBunles之后,SerializedFile这部分变为几K。
      • 序列化是啥?[1]
        • serialize = save
        • deserialize = load
      • Unity官方文档[2]的解释,大意就是说load asset的时候要从SerializedFile中deserialize信息。

      Asset loading can also be identified in CPU traces. The main method indicating an Asset load is SerializedFile::ReadObject. This method connects a binary data stream (from a file) to Unity’s serialization system, which operates via a method named Transfer. The Transfer method can be found on all Asset types, such as Textures, MonoBehaviours and Particle Systems.

      This (scene loading) requires Unity to read and deserialize all the Assets within the Scene, as denoted by the calls to various Transfer methods beneath SerializedFile::ReadObject.

  • 一些我们并没什么办法的东西

    • System.ExecutableAndDlls: 系统可执行程序和DLL,是只读的内存,用来执行所有的脚本和DLL引用。(存疑:不同平台和不同硬件得到的值会不一样,可以通过修改Player Setting的Stripping Level来调节大小。)

    • GfxClientDevice: GFX(图形加速\图形加速器\显卡 (GraphicsForce Express))客户端设备。

    • ShaderLab: Unity自带的着色器语言工具相关资源。

    • PersistentManager.Remapper: 持久化数据重映射管理相关
      与持久化数据相关,比如AssetBundle之类的。注意监控相关的文件。(存疑!实验load assetbundle并不会导致这部分内存增加。不过这部分一般只占18KB左右。


Assets

  • GameObject: code里创建的game object

  • sprite


Scene Memory

如果load一些asset再回到原来的UI,这部分基本没有变化。因为它存储的是当前的场景中各个方面的内存占用情况。

包括GameObject、所用资源、各种组件以及GameManager等(一般情况通过AssetBundle加载的不会显示在这里)
GameObject and attached components


Unity Memory API



  1. Script Serialization: https://docs.unity3d.com/Manual/script-Serialization.html

  2. SerializedFile: https://docs.unity3d.com/Manual/BestPracticeUnderstandingPerformanceInUnity1.html

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容