Unreal优化

UE4内存优化知识点整理

Spread the love

毕竟上手UE也才两个多月时间,相关的工具很多只是知道,不过大部分东西实际上是引擎无关的,一通百通。

同事分享了内存优化相关的讲座,不过实际上涉及到了很多项目相关的东西。实际上很多东西不管对于哪个项目,或者Unreal还是Unity都是通用的,在此将通用部分进行一个整理,并且将自己以前看到的一些优化相关的方法,或者相关知识点进行整理。

统计工具相关

Memreport

UE4自带工具

优点:UObject数量,内存基本状况

缺点:无法完全覆盖所有内存,如非资源类内存,并且存在反复统计覆盖的情况

Xcode Instruments

iOS自带工具

优点:可以看到所有的分配相关的堆栈

缺点:无法得知具体是哪一个物体分配,也许大量的内存由同一个函数分配,但是无法细分具体情况

关于ios内存结构可以查看我以前对Unite2018中讲座的翻译:http://www.resetoter.cn/?p=626

Android Profiler

Android Studio自带工具:https://developer.android.com/studio/profile/memory-profiler

优点:对于Java堆有比较强的针对性

缺点:数据不够详细,Native相关内存还是要用simplepref,simplepref环境配置麻烦。

用adb的命令也只能看个大概,实际上还是ios上的工具更管用。

 adb shell dumpsys meminfo <package_name|pid> [-d]

自制Lua工具

需要自己通过Lua API编写。在函数中进行hook,分析函数每次的分配。也可以通过遍历_G以及注册表来得知当前Lua虚拟机内存分布。

优点:对于Lua有针对性地进行分析

缺点:要自行实现(不过其实也还好,不是很麻烦)

LLM(Low Memory Tracker)

UE自带的内存分析工具

相关文章:

https://zhuanlan.zhihu.com/p/78005333

Memory Profiler 2

UE自带的内存分析工具

相关文章:

https://wangjie.rocks/2017/10/10/ue4-memoryprofiler/

http://www.10tiao.com/html/255/201709/2650594798/3.html

通用优化方法

不同语言间表数据共用

以前在Unity的项目中也有相似的做法,当时是C#/C++/Lua混合编程,为了三语言共用表内存,并且同时在服务器使用表工具库,当时直接在C++进行实现,并且Lua直接通过C++读表,而不走tolua,提高效率且内存只有一份。

在Unreal项目中也是一样,Lua实际上直接通过C++读取,不仅效率更高,而且节省了内存。

数据的延迟加载

表数据的延迟加载,战斗与大厅相关逻辑数据的延迟加载。

当然也涉及到及时卸载。在Unity中需要自行做引用计数,资源也一样,而Unreal中由于自带垃圾回收所以实现相关特性更加简单。

UI拆分

在Unity项目中,我们采用了一个Panel去表示一个UI的View层,Panel可以包含不同的Handler去表示不同的页签,小的组件可以由不同的Group来表示,Lua代码拆分更细,加载粒度也可以更细,玩家可以只加载需要使用的UI。

Unreal当中实际上也是一样的。只不过蛮多事情在Slate上做不如UGUI这么直观。原理实际上都是一样的。

贴图使用Texture Streaming

贴图除了使用合理的压缩方式以外,虚幻提供的StreamingTexture也是极佳的优化方式。

官方文档

这个技术是根据距离来判断使用那个层级的Mipmap,而不是同时将所有Mip层级同时载入。

UE的相关控制台参数:

r.Streaming.PoolSize,在分级中针对不同的机型可以分配不同的Pool大小,以获得合理的MipOffset。

在Real-time Rendering的19.10.1节中也对该方法有相应描述。

而且可以配合虚拟贴图使用,目前虚幻中也有相应实现。不过目前似乎还没用到。

分游戏阶段LOD

在大厅或者角色展示部分动画自然可以更精细一些,而在战斗等玩法中加载更简单的动画,自然可以减少内存。和延迟加载不太一样但是又相近,延迟加载是加载所需的,而这个则是只用够用的,Texture Streaming也是类似的做法。

美术规范制定

通过制定美术规范,约束贴图大小,以及模型面数。引擎无关。在Unity中可以使用扩展AssetImporter来约束资源导入。在Unreal中同样可以开发工具进行资源扫描。更好的方式是有专门的美术人员对提交进行Review以及约束,一般这个角色往往由TA来扮演。

在2018年的UWA开发者日上,贾伟昊的演讲说明了他们团队是如何使得资源管理变得可控,周期性的自动资源检查工具是极佳的控制手段。

Shader编译

在知乎以及其他一些网站上有队UE渲染模块比较详细的介绍与导读

https://zhuanlan.zhihu.com/p/72509370

https://zhuanlan.zhihu.com/p/72768828

减少Shader变体,控制Shader大小,在Unreal4.18中为ShaderCache,后续版本为PSO Caching。引擎提供了部分选项,例如灯光数、是否使用lightmap、是否支持雾效等剔除不需要的变体。

在打包选项中的选项可以将材质Shader部分共享,以及将跨平台格式转变为平台特定格式,通过牺牲加载时间来降低Shader大小。

结构体优化

例如在Unreal中,IPlatformFilePak.h中的FPakEntry数据结构记录了Pak挂载信息,可以将部分可以用一位替代结构体中一个字节的字段,在物体非常多的情况下也能降低不少内存。

同样的其他类似的结构体也可以通过该方式简化。在Epic Japan的分享中也有类似的优化分享。

如上图,StaticMeshResource中框出的这几处实际上大部分时候不需要用到,如果删除的话也是可观的内存优化,这篇博客有相关翻译。

同样,在Unity中AssetBundle的序列化数据占用了可观的内存大小,如果可以改源码的话实际上也可以修改这一块来做到减少内存的目的,如果不能修改源码,则可以及时卸载常驻资源的AssetBundle来避免这部分数据带来的内存消耗。

另外,一些使用字符串的字段看看是否可以尝试用id替代。例如,一些资源的路径被反复在不同的表内引用,实际上可以为不同的资源建立相应的表,其他地方通过id进行索引,可以大大减少表所占用的内存。

TCHAR字节修改

4.21中关于string进行了优化,将TCHAR的实现由4字节简化成2字节,如果还在使用较老的引擎可以尝试将这个优化合入。

内存池方式调整

在UE底层有不同的内存池分配方式。

Ansi:

默认C内存分配器

Stomp:

可以检测内存读写溢出

关于MemoryStomp:https://stackoverflow.com/questions/13669329/what-is-a-memory-stomp

TBB:

Inter有提供线程安全可伸缩分配器,如下

https://www.threadingbuildingblocks.org/tutorial-intel-tbb-scalable-memory-allocator

Jemalloc(经常被拿来与tcmalloc进行对比):

适合多线程下的内存分配管理。虽然经常与tcmalloc进行对比,但是Unreal并没有包含tcmalloc。

原理:

arena+TLS

arena即小块内存,指将大内存划分成多个小内存来管理

TLS(Thread-local storage),即线程局部缓存 回过头来看看tcmalloc,惊人的一致。

相关文章:

https://blog.csdn.net/yefeng38083120/article/details/46367527

https://zhuanlan.zhihu.com/p/48957114

Binned/Binned2

UE自己实现的内存池分配器。

实际上就是预分配大内存,然后分配合适的内存块,虽然可提高内存分配效率,但是也不可避免地实现内存浪费。在《垃圾回收的算法与实现》一书中,Mark-Sweep GC中提到的BiB-Pop法也使用了类似的方式。将该方式改为默认分配器,可以有效降低内存,但是io压力会变大。

Platform:

平台特定分配器,但是在实现中似乎没有指定对应的分配器。

流关卡加载距离调整

Level Streaming文档:https://docs.unrealengine.com/en-US/Engine/LevelStreaming/index.html

流关卡的大小可以进行切分,大小需要进行调整,如果地块过大,会导致内存上涨严重,而如果地块过小,会导致频繁IO而导致卡顿。在

其次,物体分层也是十分重要的。制作工具,将不同大小的物体分入不同粒度的地块,可以在保证精度的同时又能够保持合理的内存。在不同的游戏模式下视距也可以进行不同调整。在远处物体不重要的游戏类型中,则可以使用雾效隐藏远处细节,而减少视距,减少内存。在龙之谷手游的主城中实际上用到了类似的技术。

Unite2018上,穿越火线的讲座讲解了他们是如何通过自动化摄像机扫描来确保每一个地块LOD以及物体分布的合理性。当然,那个讲座还涉及到了很多主题,包含大小核的分配、物理数据烘焙等等。

2 thoughts on “UE4内存优化知识点整理

发表评论

电子邮件地址不会被公开。 必填项已用*标注

This site uses Akismet to reduce spam. Learn how your comment data is processed.