UE4性能观察的基础

tech2024-12-02  10

目标

关于性能分析,官方给出了些文档: 《性能及分析 | Unreal Engine Documentation》是一个目录,收集了相关的文档。 《性能与概要分析概述 | Unreal Engine Documentation》是一个整体的指南。

不过,我想从自己的思路出发讨论这个问题,收集相关资料并尝试其中的工具。所讨论的内容不限于官方文档。

讨论“游戏性能观察”

粗略来讲,我觉得“性能”可以分为时间方面和空间方面;分为CPU方面和GPU方面。

-时间空间CPU运行在CPU上的逻辑(游戏逻辑、调用图形API、引擎框架逻辑等)内存GPU执行图形API显存

对于其中每一个分类,我的思路都是:

首先,我需要有方法知道当前的总数值。例如,每一帧花费在CPU、GPU上的时间总共是多少,能不能达到30fps/60fps的目标?例如,内存总共占用了多少,显存总共占用了多少,他们到达了限制吗?这样才能知道哪个方面是需要重点关注的,而哪个方面是暂时不需要关注的。理想状态下,是知道上面的总数值是是由哪些精确的因素构成。然而因素是很多的,往往没有办法轻易掌握。一些【工具】可以帮助我分析,比如以整齐的排版或可视化的图形来表示出信息。当然了,提升相关的【知识】也能提供重要的帮助。虽然精确的因素不能全部掌握,但是存在一些方便观察,容易理解,但又占重要地位的因素。例如,“渲染”是游戏性能最常讨论的话题,而有一些因素是常常用来衡量渲染性能的,如“DrawCall数量”、“顶点数量”等。这些因素是最优先要观察的。

1. 使用“stat unit”观察帧时间瓶颈

在Cmd中输入stat unit,便可以输出一帧中的各方面处理时间: 在《如何改善虚幻引擎中的游戏线程CPU性能表现》中,有对这些时间做如下描述:

Frame(帧)时间指的是生成游戏中每一帧所需要花费的总体时间。 由于在完成一帧前会同时同步游戏线程和渲染线程,Frame时间常常接近于这些线程中的某一个时间。GPU时间衡量的是显卡需要多长时间来渲染场景。 由于GPU时间与帧同步,它的值很可能也类似于Frame时间。如果Frame时间非常接近于Game时间,那么瓶颈是游戏线程。 如果Frame时间非常接近于Draw时间,那么您的瓶颈是渲染线程。 如果Game和Draw都不怎么接近Frame,那么瓶颈就是显卡。

从官方的描述可以知道:Game对应游戏线程,Draw对应渲染线程,GPU对应显卡执行的时间。 不过其中令我感到些许困惑的是Draw和GPU的区分。按照我的理解:首先,Draw虽然叫“渲染线程”,但实际上还是运行在CPU上的(这点基本确定);但差别在于,Draw时间是调用图形API,而GPU时间是执行图形API。虽说只是“调用”,但由于牵扯到渲染状态的切换等和GPU的交流,因此时间上还是有不小的消耗;反而是GPU的“执行”的时间很多时候比想象中小。(此处的看法不太确定,待后续学习) 关于渲染线程,可以查阅官方文档,例如《线程渲染 | Unreal Engine Documentation》和《并行渲染概述 | Unreal Engine Documentation》

2. 使用【Session Frontend】观察CPU中的时间

【Session Frontend】是UE4内置的一个开发者工具,详细的介绍见官方文档《分析工具参考 | Unreal Engine Documentation》。 这里,我结合《如何改善虚幻引擎中的游戏线程CPU性能表现》中的内容,尝试使用一下这个工具。

2.1 获得分析文件

首先,在运行游戏的时候,输入Cmd(可以按~键打开Cmd),输入stat startfile: 随后就可以看到视窗左上角有显示文件已经录制的时间和当前的大小 然后,运行一段时间后(建议超过10秒,但不建议超过30分钟否则文件太大)stat stopfile 随后,就可以在项目目录/Saved/Profiling/UnrealStats/下找到刚才采集的信息

2.2 读取分析文件

打开“Session Frontend”(中文翻译为“会话前端”) 进入Profiler分页,点击Load 选择刚才的分析文件

2.3 观察分析文件中的数据

其中最重要的数据,要算底部的“ function tree”了: 内容很多,看来要想完全掌握问题,要依赖于自己掌握的“知识”了。


有一点要注意的是不要被“CPU Stall”(CPU停滞时间)迷惑,它们显示的是线程等待处理其他内容时所花费的时间,所以不需要关注。


其中一个重要的项目是FTickFunctionTask。 此项目下是正在更新的每个actor和组件。 如果游戏中存在着永不更新的actor,则可以在构造函数中:

PrimaryActorTick.bCanEverTick = false;

这样就可以完全防止其更新。

如果actor仅在某些时候进行更新,则可以在构造函数中:

PrimaryActorTick.bCanEverTick = true; PrimaryActorTick.bStartWithTickEnabled = false;

然后可以使用SetActorTickEnabled函数来启用和禁用更新。

3. 使用【GPU Visualizer】观察GPU中的时间

在Cmd中输入ProfileGPU(或者快捷键Ctrl+Shift+,)可以打开【GPU Visualizer】 其中图形化地显示了各个部分所消耗的时间: 官方文档《GPU Profiling | Unreal Engine Documentation》中有讨论了其中的几项。

4. 使用“MemReport”观察内存

MemReport命令可以用来观察内存情况。不过我并没有在官方文档中发现对其专门的详细介绍,只在《在虚幻引擎 4 中处理内存泄漏问题 - Unreal Engine》和《Debugging and Optimizing Memory - Unreal Engine》找到对它的讨论。接下来我将在这两个文档的指导下试用这个功能。

4.1 输出报告

运行游戏,在Cmd中输入memreport获取报告,或者memreport -Full表示“更加完整”的报告。 报告将存在项目目录/Saved/Profiling/MemReports/中:

4.2 阅读报告

这些.memreport的文件是简单的文本文件,可以直接打开。 一个memreport -Full生成的报告如下:(省略了列表中中间的项目)

CommandLine Options: Time Since Boot: 55.12 Seconds Platform Memory Stats for Windows Process Physical Memory: 1026.80 MB used, 1047.58 MB peak Process Virtual Memory: 1473.69 MB used, 1588.78 MB peak Physical Memory: 5037.77 MB used, 11255.99 MB free, 16293.75 MB total Virtual Memory: 8146.50 MB used, 134209584.00 MB free, 134217728.00 MB total Allocator Stats for TBB: (not implemented) Memory Stats: FMemStack (gamethread) current size = 0.00 MB FPageAllocator (all threads) allocation size [used/ unused] = [0.19 / 0.00] MB Nametable memory usage = 6.45 MB AssetRegistry memory usage = 37.47 MB 49056 - Light interaction memory - STAT_LightInteractionMemory - STATGROUP_SceneMemory - STATCAT_Advanced 521136 - Rendering mem stack memory - STAT_RenderingMemStackMemory - STATGROUP_SceneMemory - STATCAT_Advanced //省略... 66142836 - TEXTUREGROUP_World - STAT_TEXTUREGROUP_World - STATGROUP_TextureGroup - STATCAT_Advanced Obj List: -alphasort Objects: Class Count NumKB MaxKB ResExcKB ResExcDedSysKB ResExcShrSysKB ResExcDedVidKB ResExcShrVidKB ResExcUnkKB AbcImportSettings 1 0.16 0.16 0.00 0.00 0.00 0.00 0.00 0.00 AbstractNavData 2 2.52 2.52 0.00 0.00 0.00 0.00 0.00 0.00 //省略... WorldThumbnailRenderer 1 0.07 0.07 0.00 0.00 0.00 0.00 0.00 0.00 22018 Objects (Total: 37.017M / Max: 42.880M / Res: 110.862M | ResDedSys: 16.665M / ResShrSys: 0.000M / ResDedVid: 86.493M / ResShrVid: 0.000M / ResUnknown: 7.704M) RHI resource memory (not tracked by our allocator) 13104462 - Render target memory 3D - STAT_RenderTargetMemory3D - STATGROUP_RHI - STATCAT_Advanced 994184 - Structured buffer memory - STAT_StructuredBufferMemory - STATGROUP_RHI - STATCAT_Advanced //省略... 9574886 - Vertex buffer memory - STAT_VertexBufferMemory - STATGROUP_RHI - STATCAT_Advanced 483.631MB total Levels: -> /Game/Maps/UEDPIE_0_ExampleProjectWelcome Listing spawned actors in persistent level: Total: 76 TimeUnseen,TimeAlive,Distance,Class,Name,Owner 6.44, 6.44, 1260,AbstractNavData,AbstractNavData-Default,None 6.44, 6.44, 1260,CameraActor,CameraActor_0,PlayerCameraManager_0 //省略... 6.44, 6.44, 1260,PlayerState,PlayerState_0,PhysicsDemoPlayerController_C_0 Particle Dynamic Memory Stats Type,Count,MaxCount,Mem(Bytes),MaxMem(Bytes),GTMem(Bytes),GTMemMax(Bytes) Total PSysComponents,0,0,0,0,0,0 Total DynamicEmitters,0,0,0,0,0,0 //省略... Mesh,0,0 TotalMemory Taken in Pool: 0 ACTIVE,0 TotalMemory Taken by Actives: 0 Particle Order Pool Stats 0 entries for 0 bytes Config cache memory usage: FileName NumBytes MaxBytes E:/UnrealProjects/ContentSamples425/Saved/Config/Windows/Engine.ini 745980 845156 E:/UnrealProjects/ContentSamples425/Saved/Config/Windows/EditorPerProjectUserSettings.ini 412614 463008 //省略... ../../../Engine/Config/ConsoleVariables.ini 500 572 Total 3348660 3697386 Pooled Render Targets: 0.250MB 256x 256 1mip(s) HZBResultsCPU (B8G8R8A8) 0.250MB 256x 256 1mip(s) HZBResultsCPU (B8G8R8A8) //省略... 5.272MB 1208x 572 1mip(s) TemporalAA (FloatRGBA) 196.558MB total, 113.018MB used, 93 render targets Deferred Render Targets: 0.000MB Deferred total Listing all textures. MaxAllowedSize: Width x Height (Size in KB, Authored Bias), Current/InMem: Width x Height (Size in KB), Format, LODGroup, Name, Streaming, Usage Count 2048x2048 (32768 KB, 0), 2048x2048 (32768 KB), PF_FloatRGBA, TEXTUREGROUP_World, /Engine/EngineMaterials/DefaultBloomKernel.DefaultBloomKernel, NO, 0 0x0 (16384 KB, 0), 0x0 (16384 KB), PF_FloatRGBA, TEXTUREGROUP_World, /Engine/MapTemplates/Sky/DaylightAmbientCubemap.DaylightAmbientCubemap, NO, 0 //省略... 0x0 (0 KB, 0), 0x0 (0 KB), PF_Unknown, TEXTUREGROUP_World, /Script/LevelSequence.Default__LevelSequenceMediaController:MediaComponent.MediaTexture, NO, 0 Total size: InMem= 86.50 MB OnDisk= 138.21 MB Count=146, CountApplicableToMin=69 Total PF_Unknown size: InMem= 0.01 MB OnDisk= 0.01 MB Total PF_B8G8R8A8 size: InMem= 14.53 MB OnDisk= 20.57 MB //省略... Total TEXTUREGROUP_Bokeh size: InMem= 0.04 MB OnDisk= 0.35 MB Listing all sounds: 0.00 Kb for 0 resident sounds ParticleSystems: Size,Name,PSysSize,ModuleSize,ComponentSize,ComponentCount,CompResSize,CompTrueResSize 2512,/Game/ExampleContent/Blueprints/P_Impact_Ripple.P_Impact_Ripple,552,1960,0,0,0,0 2512,Total,552,1960,0,0,0,0 Obj List: class=SoundWave -alphasort Objects: Object NumKB MaxKB ResExcKB ResExcDedSysKB ResExcShrSysKB ResExcDedVidKB ResExcShrVidKB ResExcUnkKB SoundWave /Engine/EditorSounds/Notifications/CompileFailed.CompileFailed 1.32 1.32 10.83 10.83 0.00 0.00 0.00 0.00 SoundWave /Engine/EditorSounds/Notifications/CompileSuccess.CompileSuccess 1.33 1.33 11.04 11.04 0.00 0.00 0.00 0.00 Class Count NumKB MaxKB ResExcKB ResExcDedSysKB ResExcShrSysKB ResExcDedVidKB ResExcShrVidKB ResExcUnkKB SoundWave 2 2.65 2.65 21.87 21.87 0.00 0.00 0.00 0.00 2 Objects (Total: 0.003M / Max: 0.003M / Res: 0.021M | ResDedSys: 0.021M / ResShrSys: 0.000M / ResDedVid: 0.000M / ResShrVid: 0.000M / ResUnknown: 0.000M) Obj List: class=SkeletalMesh -alphasort Objects: Object NumKB MaxKB ResExcKB ResExcDedSysKB ResExcShrSysKB ResExcDedVidKB ResExcShrVidKB ResExcUnkKB SkeletalMesh /Game/Character/HeroTPP.HeroTPP 659.01 686.32 323.36 21.78 0.00 0.00 0.00 301.57 Class Count NumKB MaxKB ResExcKB ResExcDedSysKB ResExcShrSysKB ResExcDedVidKB ResExcShrVidKB ResExcUnkKB SkeletalMesh 1 659.01 686.32 323.36 21.78 0.00 0.00 0.00 301.57 1 Objects (Total: 0.644M / Max: 0.670M / Res: 0.316M | ResDedSys: 0.021M / ResShrSys: 0.000M / ResDedVid: 0.000M / ResShrVid: 0.000M / ResUnknown: 0.295M) //省略...

值得一提的是,用 【差异工具】 很有用,因为它们经过排序,因此可以正确区分。


报告的第一部分列出了整体内存使用情况,以及有关特定于平台的内存使用情况。

Platform Memory Stats for Windows Process Physical Memory: 1026.80 MB used, 1047.58 MB peak Process Virtual Memory: 1473.69 MB used, 1588.78 MB peak Physical Memory: 5037.77 MB used, 11255.99 MB free, 16293.75 MB total Virtual Memory: 8146.50 MB used, 134209584.00 MB free, 134217728.00 MB total

随后,是已经注册的统计信息:

Allocator Stats for TBB: (not implemented) Memory Stats: FMemStack (gamethread) current size = 0.00 MB FPageAllocator (all threads) allocation size [used/ unused] = [0.19 / 0.00] MB Nametable memory usage = 6.45 MB AssetRegistry memory usage = 37.47 MB 49056 - Light interaction memory - STAT_LightInteractionMemory - STATGROUP_SceneMemory - STATCAT_Advanced 521136 - Rendering mem stack memory - STAT_RenderingMemStackMemory - STATGROUP_SceneMemory - STATCAT_Advanced //省略... 66142836 - TEXTUREGROUP_World - STAT_TEXTUREGROUP_World - STATGROUP_TextureGroup - STATCAT_Advanced

对于其中的每一项,例如Light interaction memory,可以在源代码中搜索STAT_LightInteractionMemory来获得更详细的信息:


接下来是Obj List: -alphasort(以字母排序的物体的列表)

Obj List: -alphasort Objects: Class Count NumKB MaxKB ResExcKB ResExcDedSysKB ResExcShrSysKB ResExcDedVidKB ResExcShrVidKB ResExcUnkKB AbcImportSettings 1 0.16 0.16 0.00 0.00 0.00 0.00 0.00 0.00 AbstractNavData 2 2.52 2.52 0.00 0.00 0.00 0.00 0.00 0.00 //省略... WorldThumbnailRenderer 1 0.07 0.07 0.00 0.00 0.00 0.00 0.00 0.00 22018 Objects (Total: 37.017M / Max: 42.880M / Res: 110.862M | ResDedSys: 16.665M / ResShrSys: 0.000M / ResDedVid: 86.493M / ResShrVid: 0.000M / ResUnknown: 7.704M)

它显示了每一类UObject以及它们使用了多少内存。


接下来是渲染内存

RHI resource memory (not tracked by our allocator) 13104462 - Render target memory 3D - STAT_RenderTargetMemory3D - STATGROUP_RHI - STATCAT_Advanced 994184 - Structured buffer memory - STAT_StructuredBufferMemory - STATGROUP_RHI - STATCAT_Advanced //省略... 9574886 - Vertex buffer memory - STAT_VertexBufferMemory - STATGROUP_RHI - STATCAT_Advanced 483.631MB total

接下来是Streaming Levels:

Levels: -> /Game/Maps/UEDPIE_0_ExampleProjectWelcome

接下来是关卡中生成的Actors:

Listing spawned actors in persistent level: Total: 76 TimeUnseen,TimeAlive,Distance,Class,Name,Owner 6.44, 6.44, 1260,AbstractNavData,AbstractNavData-Default,None 6.44, 6.44, 1260,CameraActor,CameraActor_0,PlayerCameraManager_0 //省略... 6.44, 6.44, 1260,PlayerState,PlayerState_0,PhysicsDemoPlayerController_C_0

5. 切换 视图模式 来观察渲染方面的数据

在关卡编辑器中可以切换【视图模式】:

5.1 网格模式(Brush Wireframe)

网格模式可以观察当前顶点的情况。可以观察到哪个部分的顶点过于密集,这可能代表着那个模型需要做LOD。

5.2 着色器复杂度(Shader Complexity)

着色器复杂度可以观察到哪部分花费了太多的像素着色器工作量,对于数值较高的部分,需要衡量下达到的效果和所耗费的性能了。

6. 使用一些统计命令(stat …)观察一些渲染相关数据

6.1 三角形数目

stat engine命令: 可以显示一些三角形数目,例如Static Mesh Tris代表了StaticMesh的三角形数目

6.2 Draw Call

stat SceneRendering命令:

7. 在材质编辑器内查看材质的相关数据

可以显示指令数、Sampler数目 等等。。。

8. 使用【统计数据】窗口

有多个分类: 比如“Primitive统计数据”:

其他工具

1)其他 Stat命令

所有的统计数据可以在这里找到: 《Stat命令 | Unreal Engine Documentation》中有对其中进行介绍。

2)使用【MallocProfiler】观察内存

关于这个工具并没有找到官方文档,但在《UE4内存Profiler - 知乎》中有其讨论。

3)英特尔® 图形性能分析器

英特尔提供了免费的图形分析器:Intel® Graphics Performance Analyzers 官方教程文档见:《Unreal Engine 4 优化教程 第一部分》

4)RenderDoc

RenderDoc在UE4中使用的官方文档:《RenderDoc | Unreal Engine Documentation》

5)Unreal Insights

《Unreal Insights | Unreal Engine Documentation》

官方的建议

官方文档《写给美术师和设计师的性能指南 | Unreal Engine Documentation》为非技术人员从一般角度提出了些建议,我觉得很有参考价值。

《粒子系统的核心优化概念 | Unreal Engine Documentation》中有针对于粒子系统的优化建议。

其他问题与未来学习的方向

1)显存怎么看?

我发现GPU-Z中可以看到当前计算机显卡的整体显存: 不过这是一个总体的值,并没有区别UE4引擎所消耗的。 那么如何正确的观察UE4游戏所消耗的显存呢?更进一步,有办法知道显存的具体的分配情况吗?

2)游戏线程、渲染线程、GPU之间的同步

《并行渲染概述 | Unreal Engine Documentation》

最新回复(0)