3.0.0 Native Metal 渲染内存问题

  • Creator 版本: 3.0.0

  • 目标平台: iOS

  • 测试机型:iPhone 5s 内存 1G 达到 500 左右峰值,会出现 OOM

希望在低端机型上的支持更加完善,不清楚具体是 MTL 后端问题还是其他什么原因,目前进入游戏场景,除资源外,引擎本身需要 100- 150M 左右的内存是否合理?

详细情况

我们的需求场景是将游戏业务放在二级页面,可以重复进入

感兴趣的同学可以看下内存曲线,未进入游戏前 48M,进入后飙升到 200M。游戏部分是空场景

空场景趋势图

以下是空场景下进入游戏内的内存情况,从 40 到 132M

带 3D场景的趋势

包括一个场景,多个 Node 以及 3D 人物

退出后,还有部分内存无法释放,约 20M 左右,集中在 MTLCommandBuffer 这部分

进入游戏后

退出游戏后,存在部分内存无法释放(不包括 v8 常驻内存)

说下你们是怎么做的呗?

退出游戏部分该有的清理应该都差不多,除此之外,还需要三步

  1. 清理资源,assetManager release all。预期能减少很多,我们这边验证可以减少 200+
  2. 清理未释放的 MTL 相关引用,具体需要改 native engine,可以看上面的图或者自己分析哪些应该释放但没有释放。不是内存泄露
  3. 资源分包,适当在切场景或者替换 node 时把之前的资源清理掉,避免内存一直暴涨

可以参考下

目前还没有处理退出游戏前的资源清理,不过这个应该影响不大。应用程序都退出了,所有的资源也都会被系统回收。

您这里说的退出游戏前的资源清理指的是游戏脚本层还是 native engine 层?由于在 iOS 上我们会将游戏放在二级页面,返回主页面的时候会销毁游戏,并且会再次进入游戏,所以需要考虑资源清理的问题,影响还是很大的。不然每次都会有部分内存没有回收,导致 OOM。

我指的是windows/mac/android 等退出应用程序时的事件通知到 脚本层。和你说的可能不太一样。

你这里指的是网页游戏吧?

我和 @yuhanle 都指的都是 iOS 上的游戏,我们是一款教育产品,将游戏场景嵌入到 iOS app 里,而不是整个游戏是一个应用程序。所以和您说的也不大一致。所以我们遇到了退出游戏时部分游戏资源没有回收的问题,可以提供一些方案思路吗?

明白了,那处理的思路应该是类似的。也是退出游戏需要清理资源的问题。我的思路是这样的:

  • 游戏推出前发送事件到脚本层
  • 脚本层监听事件并清理资源。
  • 至于有哪些模块需要清理资源目前还没有梳理,所以也没法给出完整的清单。需要清理的资源我目前能想到的是 GPU 创建出来的资源,主要是 buffer 和 texture。还有可能是引擎本身的一些缓存。
1赞

至于引擎本身消耗比较多的内存,我们正在跟进。

确实,目前我们在 native engine C++ 层观察到没有释放的大部分内存是 MTLCommandBuffer 和 MTLTexture,我们创建了类似 CCMTLGPUGarbageCollectionPool 这样的类来清理内存暂时解决部分问题。但还是希望引擎组后期提供官方的方案 :grinning:

MTLCommandBuffer :grinning: :grinning: :grinning:

好的。非常感谢,这部分有预期的时间或者在哪个版本会优化吗

非常关注!

Hi, 有两个方法可以显著降低内存占用率,不过稍微涉及到native engine的变动:

  1. MTLGPUObjects.h里面为CCMTLGPUStagingBufferPool开辟的预留内存默认是16M,加上triple-buffer所以即使什么都不做也会申请相对较大的一块内存。如果不需要这么大可以自行定义大小,比如
    constexpr size_t chunkSize = 1 * 1024 * 1024; // 1M per block by default

  2. 为了上层的对象复用有些对象destroy之后还是存留着的,可以手动触发GC
    ScriptEngine::getInstance()->garbageCollect();
    比如放在某些需要释放内存的事件监听里面。

预计在 3.3 版本。

好的,我们会根据你的建议尝试进一步优化,感谢

3.3岂不是得今年年尾?

关注,希望官方重视下这个问题。

内部已经在看了。