首先,上线各大渠道要看应用的总内存量。总内存包含了我们在Unity Profiler的Memory面板上看到的Reserved Total数字的值,再加上除Unity以外的内存。但是很多时候,这个总内存要比Unity Profiler多出来一个量级。以我们的项目为例,iOS总内存为408MB,Unity Reserved Total为279.4MB,多出来408-279.4=128.6MB。
天了噜!这些暗箱里的东西都是什么?我打算从完整项目开始做减法,分别测试一探究竟。
先上我测试用的代码,下面分别是iOS和Android的获取总内存的代码。
iOS的c代码:
Android的java代码:
c#代码:
然后分别测试的结果如下:
结论 | |||||||||||||||||||||||
游戏项目|完整 | 屏蔽oc的代码就是指替换UnityAppController.mm,UnityView.mm文件,使在objective-c层面的代码屏蔽 | ||||||||||||||||||||||
Xcode Run | |||||||||||||||||||||||
内存值 | |||||||||||||||||||||||
带有sdk启动的代码|Development Build | 104.81 | ||||||||||||||||||||||
屏蔽oc的代码|Development Build | 86.14 | ||||||||||||||||||||||
Xcode Profile|Instrument | |||||||||||||||||||||||
带有sdk启动的代码|Development Build | 101 | ||||||||||||||||||||||
屏蔽oc的代码|Development Build | 82.5 | ||||||||||||||||||||||
游戏项目|去掉了其他场景 | 内存减少了18.5MB,初步结论是各路sdk的native代码项就占用了18.5MB的app内存 | ||||||||||||||||||||||
Xcode Run | |||||||||||||||||||||||
内存值 | |||||||||||||||||||||||
带有sdk启动的代码|Development Build | |||||||||||||||||||||||
屏蔽oc的代码|Development Build | |||||||||||||||||||||||
Xcode Profile|Instrument | |||||||||||||||||||||||
内存值 | |||||||||||||||||||||||
带有sdk启动的代码|Development Build | 101 | ||||||||||||||||||||||
屏蔽oc的代码|Development Build | |||||||||||||||||||||||
游戏项目|去掉了其他场景|去掉了所有代码和引用库 | 内存减少了47.4MB,结论是il2cpp的代码的初始化内存占用了很大的一部分 | ||||||||||||||||||||||
如果可以用减法的话,47.4-18.5=28.9MB,这是il2cpp所占用的内存 | |||||||||||||||||||||||
Xcode Run | |||||||||||||||||||||||
内存值 | |||||||||||||||||||||||
Development Build | 55.2 | ||||||||||||||||||||||
Xcode Profile|Instrument | |||||||||||||||||||||||
内存值 | |||||||||||||||||||||||
Development Build | 53.6 | ||||||||||||||||||||||
游戏项目|去掉了其他场景|去掉了所有代码和引用库|去掉了StreamingAssets | 无明显变化,结论是StreamingAssets在iOS下有绝对文件路径,所以不需要单独索引 | ||||||||||||||||||||||
而且项目的StreamingAssets文件数量不多 | |||||||||||||||||||||||
Xcode Profile|Instrument | |||||||||||||||||||||||
内存值 | |||||||||||||||||||||||
Development Build | 53.5 | ||||||||||||||||||||||
游戏项目|去掉了其他场景|去掉了所有代码和引用库|去掉了StreamingAssets|去掉了所有Resources文件夹 | 内存减少了20MB,结论是Unity在native层面进行的资源索引,这里和安卓的dalvik堆相似 | ||||||||||||||||||||||
Xcode Run | |||||||||||||||||||||||
内存值 | |||||||||||||||||||||||
Development Build | |||||||||||||||||||||||
Xcode Profile|Instrument | |||||||||||||||||||||||
内存值 | |||||||||||||||||||||||
Development Build | 35.4 | ||||||||||||||||||||||
无其他代码的项目 | |||||||||||||||||||||||
Xcode Run | |||||||||||||||||||||||
内存值 | |||||||||||||||||||||||
Development Build | 31.8 | ||||||||||||||||||||||
Xcode Profile|Instrument | |||||||||||||||||||||||
内存值 | |||||||||||||||||||||||
Development Build | 31 | ||||||||||||||||||||||
Xcode Profile|Instrument|Release | |||||||||||||||||||||||
No Development Build | 30 | ||||||||||||||||||||||
总结:iOS内存测试报表里的128MB内存,包含了:18MB的sdk相关oc代码,28.9MB的代码相关代码(猜测为il2cpp的初始化内存分配),20MB的Resources文件夹分配索引的代码。
在这个层面可优化的点不多。针对以上三项:
- sdk的代码层面的内存优化,我们接入的是MSDK,这里相信腾讯,问题先放置了。
- il2cpp的代码占用,只能通过减少总代码量来进行,及时清理无用代码,特别是第三方的库。
- Resources文件夹的内存:这个问题比较复杂,参考:https://unity3d.com/cn/learn/tutorials/topics/best-practices/guide-assetbundles-and-resources
总的来说就是,Resources文件夹下面的所有文件,无论使用与否都会被打包出来。Unity引擎会在打包的时候,判断项目文件夹下面的需要打包的资源文件。
这些资源将要被打包:
- 所有Resources文件夹下的文件,及其引用到的所有资源。 例如我们把图集资源放到Resources文件夹外面,但是把引用到了这个图集的UIPrefab放到Resources文件夹里面,那么图集也会被打包。
- 获取在BuildSetting面板里面Scenes In Build窗口,获取所有已激活场景文件,并且找到这些场景文件引用到的所有资源。
- 所有的代码文件
- 所有的Plugins/当前平台 的文件
- StreamingAssets文件,这部分文件比较特殊,在iOS下有绝对文件路径,在Android下没有,具体可以参考手册。
而Unity引擎在程序启动时会对所有的资源文件弄一个映射,这个映射的内存就是多出来的这一块内存,内存大小和打包的所有资源文件的数量(非大小)成正比。在Android下同样也可以看见,随着增/减Resources文件夹的文件数量,dalvik堆的内存也随之增加/减少,也是这个原理。还有一份内存是可以在Unity Profiler/Memory/Detailed里面看见,显示在Assets/ResourceManager的内存。这部分内存也是常驻,并且也随打包的所有资源文件的数量(非大小)成正比。
关于Resources文件夹,有的Resources文件夹都不在Assets/Resources这里,而是随意放置,不能统一管理。而且有些也是无用资源,清理打包后的无用资源可以用这个插件 Build Report Tool:https://www.assetstore.unity3d.com/en/#!/content/8162
先总结到这里。。2017年的第一篇博客总算写出来了,Markdown还不熟悉很蛋疼啊。万事开头难,加油。