BlueRoseNote/03-UnrealEngine/性能优化/UnrealInsight以及其他性能监测工具.md

25 KiB
Raw Permalink Blame History

title, date, excerpt, tags, rating
title date excerpt tags rating
UnrealInsight以及其他性能监测工具 2022-08-10 22:18:31 Profiler

前言

目前主要使用的是Unreal Insights。其他工具有

  • Stat用于实时显示数据。
  • GPU Profiler用于显示简单的GPU性能损耗情况。
  • UnrealFrontend Profiler似乎已经被Unreal Insights代替。

Unreal Insights

与Profiler 的对比

  • Profiler 只能记录 CPU 侧的开销信息Unreal Insights 对 CPU, GPU 的信息都能捕获到
  • Profiler 能够直接从 Editor 内部打开并检测 Editor 下的性能Unreal Insights 只能作为独立应用打开,且必须通过添加启动参数才能统计到 Editor 的性能数据
  • Profiler 对 Game Thread 的瓶颈定位分析粒度更小,能精确定位到开销较大的某个函数
  • Unreal Insights 作为应用程序的性能更优,能更大程度上减少在本地进行性能检测时造成的额外影响
  • Unreal Insights 支持远程监测,彻底消除 Profiling 本身对性能检测结果的影响
  • Unreal Insights 在信息可视化上明显优于 Profiler有更加具有辨识度的色彩、便捷的操作和良好的交互体验

用法

  1. 启动UnrealInsights其路径为Engine\Binaries\Win64\UnrealInsights.exe
  2. 在工程或者游戏中启用trace命令。
  3. 此时UnrealInsights会显示连接上的Session双击这个Session即可查看相关信息。

PS.在Windows上开发打开了UE客户端会自动去连接Unreal Insights。trace的方法默认情况下会生成.utrace文件可以设置-tracefile=PATH设置生成的路径和文件名也可以使用.

客户端

非Shipping版本的独立客户端命令行启动进行数据追踪。命令行需要附带运行工程以及 -trace=cpu,gpu,frame,log命令。例如 D:\UnrealEngine\UE_4.27\Engine\Binaries\Win64\UE4Editor.exe D:\Work\Lyra\Lyra.uproject -game -WINDOWED -ResX=1280 -ResY=720 -trace=cpu,gpu,frame,log

编辑器启动的游戏等可以打开命令窗口输入:

trace.start frame,cpu,gpu | trace.stop 开始停止数据追踪

生成的.utrace文件会出现在项目的默认剖析目录中(.../Saved/Profiling)

专用服务器

非shipping版本的ds,启动参数添加需要启动参数:

-tracehost=127.0.0.1 -trace=cpu,frame,bookmark,log,loadtime,file,net,gpu,counters,animation -statnamedevents

会生成.utrace文件. 可以使用-tracefile=PATH 设置文件生成的目录。

远程追踪

凭借Android Debug Bridge (adb)Android工具可通过USB线重定向TCP流量。要在Android设备上连接运行时应用程序首先指示adb经由设备上通过USB建立的TCP连接传递

adb.exe reverse tcp:1980 tcp:1980

Unreal Insights聆听TCP端口1980。 在设备上运行时应连接到 localhost因此操作系统将通过USB线路由流量。

-tracehost=127.0.0.1
  1. 手机端开启开发者模式数据线连接PC保持adb连接状态运行adb reverse tcp:1980 tcp:1980
  2. PC端启动Unreal Insights自动监听1980端口
  3. 设置android手机包的启动参数通过UE4CommandLine.txt。UE4CommandLine.txt文件中添加
-tracehost=127.0.0.1 -trace=cpu,frame,bookmark,log,loadtime,file,net,gpu,counters,animation -statnamedevents

运行adb push <path_to>\UE4CommandLine.txt /mnt/sdcard/UE4Game/<project_name>/UE4CommandLine.txt 将文件放入手机项目相关目录。 4. 启动app. PC端Unreal Insights上可以看到手机Trace Session的Status变为LIVE。双击连接即可实时看到数据。同时.utrace文件也会被传到PC端

参数

命令行选项 用途 说明
-statnamedevents CPUPROFILERTRACE_ENABLED 开启指定的追踪事件,若结合 -trace=cpu此选项将激活更多CPU时间事件。
-trace -trace=cpu,frame,bookmark,... 追踪指定的Channel
-tracehost tracehost=X -tracehost 的更多详情,请参阅Unreal Insights介绍

可用追踪的channel包括

  • Log
  • Bookmark
  • Frame
  • CPU
  • GPU
  • LoadTime
  • File
  • Net

Stat

官方文档:Stat命令 参考文章:UE4 性能 - (一)瓶颈定位

用于在屏幕上试试显示各种参数,常用的命令主要有:

  • Stat Fps
  • Stat Unit
    • Frame: 即一帧所耗费的总时间。
    • Game: CPU Gameplay线程处理游戏逻辑所耗费的时间。
    • Draw: CPU渲染线程准备好所有必要的渲染所需的信息并把它从 CPU 发送给 GPU 所耗费的时间 。
    • GPU: GPU接收到渲染所需信息之后将像素最终的表现画在屏幕上的耗时
  • Stat UnitGraph:显示实时图标。
  • Stat UnitMax
  • stat gameGame逻辑消耗情况。
  • stat initviews:渲染物体剔除损耗情况。
  • stat SceneRendering Draw Call情况。
  • stat streaming overview贴图流占用内存情况。
  • stat startfile/stat stopfile:开始/停止记录性能情况快照,最后会生成*.ue4stats。该文件可以使用[UnrealFrontend Profiler]打开。
  • stat slow/stat stopslow:开始/停止获取实时数据。比如stat slow 0.01 10这将会渲染在过去的10秒内所有运行时间超过10毫秒的循环统计数据。

Stat也可以通过点击ViewportOption的Stat进行开启

GPU

主要的工具:

  • GPUProfile
  • 第三方GPU调试工具
    • RenderDoc
    • NSight GraphicN卡
    • Radeon GPU ProfilerA卡
    • PIX微软
    • GPAInter

如果有条件还是使用RenderDoc来调试比较好。建议先关闭帧数限制- r.VSync 可以关闭垂直同步):

GPUProfile

按下Ctrl+shift+, 或 者控制台命令: ProfileGPU打开:

可以看出影响GPU瓶颈最主要的是BasePassPrePass 。

  • **PrePass RenderPrePass
  • Base pass RenderBasePass / TBasePassDrawingPolicy。
    • 渲染不透明和遮盖的材质,向 GBuffer 输出材质属性。
    • 光照图贡献和天空光照也会在此计算并加入场景颜色。
  • Lighting
    • 阴影图将对各个光照渲染,光照贡献会累加到场景颜色,并使用标准延迟和平铺延迟着色。光照也会在透明光照体积中累加。
  • Fog
    • 雾和大气在延迟通道中对不透明表面进行逐个像素计算。
  • Post Processing
    • 多种后期处理效果均通过 GBuffers 应用。透明度将合成到场景中。
    • 其中 BasePass 0 =不透明网格。BasePass 1 =用于Z深度的Alpha蒙版不透明网格。BasePass Dynamic =动画顶点,如SkeletalGeoCacheAlembic

几个值得注意的数据项:

  • Base Pass
  • Deferred Decals
  • Lighting
  • SSR环境反射
  • Translucency(半透明)
  • Postprocessing(后期处理效果)
  • Particle粒子

材质复杂度

材质复杂程度在这里可以查看,越红的越消耗,原则上减少使用点动画和曲面细分等一些效果。**红色:**意味着性能消耗非常高 绿色:意味着性能消耗最低半透明:意味着增加性能消耗

CPU

Game Thread

Game Thread 造成的开销,基本可以归因于 C++ 和蓝图的逻辑处理瓶颈常见于Tick 和高复杂度逻辑。大量物体同时 Tick 会严重影响 Game Thread 的耗时。 针对Tick可使用

  • stat game:显示 Tick 的耗时情况
  • dumpticks:可将所有正在 tick 的 actor 打印到 log 中
    • dumpticks grouped
  • stat tickables
  • listtimers
  • stat uobjects
  • #MOVING SCENE COMPONENTS

复杂逻辑:需要借助 Unreal Frontend Profiler / Unreal Insights 等工具对游戏逻辑中开销较大的代码进行定位。

LandscapeSubsystem Tick

主要是在更新Grass。在非编辑器下的 Game 模式,可以通过 Console Variable grass.TickInterval 来设置更新间隔,其数值会被 clamp 在 1 到 60 之间。 或者极端点的直接grass.Enable 0

UE5.2 LandscapeGrass.cpp

static void GrassCVarSinkFunction()  
{  
    static float CachedGrassDensityScale = 1.0f;  
    float GrassDensityScale = GGrassDensityScale;  
  
    if (FApp::IsGame())  
    {       ALandscapeProxy::SetGrassUpdateInterval(FMath::Clamp<int32>(GGrassTickInterval, 1, 60));  
    }
...
}

Draw Thread (Rendering Thread)

Draw Thread 的主要开销来源于 Visibility Culling 和 Draw Call

Visibility Culling 会基于深度缓存(Depth Buffer) 信息,剔除位于相机的视锥体(Frustum)之外的物体和被遮挡住(Occluded)的物体,当游戏世界中可见的物体过多,剔除所需的计算量也将变大,导致耗时过长

  • stat initviews:显示 Visibility Culling 的耗时情况,同时还能显示当前场景中可见的 Static Mesh 的数量(Visible Static Mesh Elements)

Draw Call为CPU向GPU提交渲染数据的过程。在UE中只要将多边形赋予相同的Materials引擎将会自动合并Batch这个过程叫做合批。合批工具一般会把相同ShaderModel的材质合并到一起来实现具体就是把多个材质所用到的贴图合并到一起在一个材质中使用。并且使用一个Index来控制当前材质。

  • stat SceneRendering 可查看 Mesh Draw Call 的数量
  • 相比于面数,Draw Call 对性能开销的影响要大得多

GPU Thread

  • 顶点瓶颈(Vertex-bound)

    • Dynamic Shadow
      • 目前动态阴影(Dynamic Shadow)的生成主要依赖 Shadow MappingShadow Mapping 每生成一次阴影需要进行两次光栅化,因此当顶点数过多(可能源于多边形数量巨大,也可能源于不适当的曲面细分) 时Dynamic Shadow 将成为 GPU 在光栅化阶段的一大性能瓶颈
      • ShowFlag.DynamicShadows 0: 使用该指令可关闭场景内的动态阴影(0表示关闭1表示开启),可在开启和关闭两种状态间反复切换,查看卡顿情况是否发生明显变化,以此判断 Dynamic Shadow 是否确实造成了巨大开销
  • 着色瓶颈(Pixel-bound)

    • 运行指令 r.ScreenPercentage 50,表示将渲染的像素数量减半(也可替换成其他 0-100 之间的数),观察卡顿现象是否明显减缓,以此判断瓶颈是否 Pixel-bound
    • Shader Complexity
      • 显示对每一个像素所执行的着色指令数量,数量越多,消耗越大
      • 场景中存在过多的半透明物体(Translucent Object),会显著增加 Pixel Shader 的计算压力,使用 stat SceneRendering 可查看 Translucency 的消耗情况;使用 ShowFlag.Translucency 0 来关闭(0表示关闭1表示开启)所有半透明效果
      • 当Shader的实现逻辑过于复杂或低效时也会导致较高的 Shader Complexity
      • 在 Viewport 中选择 Optimization Viewmodes → Shader Complexity可视化 Shader 造成的开销
  • Quad Overdraw

  • 着色期间 GPU 的大部分操作不是基于单个像素,而是一块一块地绘制,这个块就叫 Quad,是由 4 个像素 (2 × 2) 组成的像素块

  • 当模型存在较多狭长、细小的三角形时,有效面积较小,但可能占用了很多 QuadQuad 被多次重复绘制,会导致大量像素参与到无意义的计算中,引起不必要的性能开销

  • 进入 Optimization Viewmodes → Quad Overdraw,显示 GPU 对每个 Quad 的绘制次数

  • Light Complexity

    • 场景内的动态光源(Dynamic Lights)数量过多时,会产生大量动态阴影(Dynamic Shadow)_如上述所说容易引起较大开销
    • 动态光源的半径过大,导致多个光源的范围出现大量交叠,也可能导致严重的 Overdraw 问题
    • 进入 Optimization Viewmodes → Light Complexity,查看灯光引起的性能开销
  • 内存(Memory-bound)_引起的瓶颈

    • 有时性能瓶颈还在于过高的内存占用,其中最常见的是大量的纹理(Texture)_加载和采样
    • 使用 stat streaming overview,查看当前纹理对内存的占用情况
    • 对于纹理的优化,后续将另开新篇加以详细介绍

内存

  • MEMREPORT -full
    • Runs a number of individual commands for memory profiling
  • obj list class=
    • Example: obj list class=AnimSequence
  • Only in Packaged Builds
    • Example: AnimSequence twice as large in editor builds.

这样就就可以查看指定Object的内存占用情况。

COLLISION & PHYSICS

  • Unreal configured to work out of the box.
    • “Collision Enabled” => Physics + Query
    • Most things require just QueryOnly
  • Disable on components players cant reach or interact with.
  • Profiling
    • stat physics, stat collision
    • obj list class=BodySetup
    • show CollisionPawn, show CollisionVisibility
  • Tip: Landscape may use lower collision MIPs

MOVING SCENE COMPONENTS

移动场景组件可能会造成一些性能问题,需要注意以下几点:

  • Move/Rotate only once per frame
  • Disable Collision & GenerateOverlaps=False
  • AutoManageAttachment
    • Audio & Niagara
  • Profiling
    • stat component

MOVING COMPONENTS - BOUNDS

  • UseAttachParentBound=True
    • Skips “CalcBounds”
  • 检查命令show Bounds / showflag.bounds 1

蓝图中勾选UseAttachParentBound以此跳过计算CalcBounds的问题。

UnrealFrontend Profiler

官方文档:Profiler Tool 其他参考文章:

常见操作流程

  • 运行游戏,切换到 Profiler 界面
  • Main Toolbar 中点击 Data Preview 开始预览性能数据
  • 关注 Data Graph Full 内是否出现明显尖峰,如果有并希望马上查看原因,则再次点击 Data Preview 停止预览
  • 拖动 Data Graph Full 中的绿色滑窗至尖峰处,开始观察 Data Graph 界面,准确定位导致开销陡升发生在哪一帧或哪一小段
  • Data Graph 中选择一段时长范围,此时 Event Graph 将显示这段时长内各方法的耗时情况,按降序排列
  • Event GraphMain Event Graph 区域展开条目层级,根据 Function Details 区域显示的信息,一级级深入定位到具体的方法上

游戏线程分析

查看游戏线程的性能表现的最佳工具是使用统计数据分析程序。 在控制台输入“stat startfile”来启动分析 等10秒左右输入“stat stopfile”收集这10秒的平均值当然也可以等更多的时间。 在路径Saved/Profiling/UnrealStats下,会有关于您项目文件夹的ue4stats文件。 也可以用“stat slow”来获取实时的报告,它可以通过报告运行一帧中特定时间段**(默认10毫秒**)来逐步定位帧停顿的位置。 运行速度较慢的数据将会在HUD上显示一段时间,从而判断性能波动。 “Stat stopslow”来关闭它。 参数以秒为单位(所以10ms也就是0.01秒)参数可设置持续的时间,默认值是10秒。 **例:**STAT SLOW 0.01 10这将会渲染在过去的10秒内所有运行时间超过10毫秒的循环统计数据。

现在我们需要分析,需要打开编辑器中的Session Frontend(会话前端)

当您打开了会话前端选项卡后,您需要切换到Profiler(分析程序)的小选项卡。在该处,您可以选择载入您最近捕获的ue4stats分析文件。

加载后会这样显示

  1. 渲染线程vs游戏线程的简图
    • 根据CPU逻辑与渲染的关系一眼你就会知道你是否是CPU受限的或者它是否是与游戏相关的且花费最多性能的逻辑。
  2. 抓取期间的整个CPU加载的简图
    • 在这里你可以沿着时间线单击任何部分来观察对应帧的CPU分析或者你可以单击、拖拽来选择帧的范围并且查看均值。根据你这里的选择函数时间3的层级列表中的分析数据会改变。
  3. 调用的不同函数和所花时间的层级列表
    • 花费时间最长的函数排在顶端。花费最多时间的函数以红色显示,其它用黑色显示。你可以通过单击左侧三角来展开对应层,你可以看到这个函数调用过程的分解以及执行花费的时间。 注意这里的CPU停转是CPU闲置等待其它线程结束的时间
  4. 如果你在函数时间3的层级列表中选择了特定的函数你可以看到这里的显示变化这里显示了什么函数调用了这个函数以及该函数调用了哪些函数同时可以看到这些调用和被调用函数执行时间的比例。
  5. 左侧面板展示了stats和stat组。顶层是stat组你可以展开它查看内部的独立stat。这些stat可以是整型、浮点型数字或者内存你可以控制哪些显示在stat过滤器面板6中。如果你鼠标停留在一个stat上会弹出该stat的分析信息8
  6. 在这里你可以通过搜索想要的stat、改变分组和排序、隐藏/显示不同类型的stat浮点/整型/内存)以及启用/禁用层级视图控制stat面板的显示5
  7. 这些控件用于显示函数时间的层级列表和所选函数的分解信息4
    1. 类型
      • 如果在图像视图中你只选择了一帧2你唯一的选择就是显示信息那帧但是如果你选择了一系列帧你可以选择是否显示平均时间或者花费的最长时间。
    2. 视图模式
      • 这会改变函数时间分层的层级列表视图3或者改变单纯的函数列表里面包括这些函数的子程序包括的或排除的时间。
    3. 向前、向后按钮可以让你在图像视图的不同部分之间跳转2
      • 所有你可以看到一系列信息,之后缩小你的选择范围直到一个帧,然后用这些按钮来在两者之间切换。下拉箭头显示了之前的选择。
    4. 这里的火焰按钮是用来展开你当前选择函数的时间层级列表的3
      • 用来查找花费最多时间的路径,它也会用一个小火焰图标来标识该路径。
  8. 鼠标在stat面板5的一个stat上面停留时会显示关于该stat的分析信息最重要的是最小值、平均值和最大值

这里我们只关注几个选项,展开**GameThread(游戏线程)**项目,然后往下拉,直到您看到超过几毫秒的“Inc Time”(包含时间)条目,而且其不包含许多子项或不包含任何子项。 同时关注一下“Calls”(调用)数列,它显示了每帧调用的统计数据的平均次数。 不要被“CPU StallCPU停滞时间项目弄糊涂了。 它们显示的是线程等待处理其他内容时所花费的时间,所以不是主要数据,而且仅仅会在帧频率受限或者游戏进程不为瓶颈时才会显示出来。

  • 还有一个重要项目TickFunctionTask

此项目下是正在更新的每个actor和组件。 一般来说,降低每帧更新的actor和组件的数量都可以很好地加速游戏。

  • 另一个要关注的是BlueprintTime蓝图时间

找到这个值的最佳方法是切换到包含(合并)视图并在列表中找到它。 这样就可以把所有的BlueprintTime蓝图时间)条目组合到单一行中。 如果您选择BlueprintTime蓝图时间,然后切换回层次视图,则其会选择所有蓝图代码被执行的位置,这样能让您很好地了解花费时间进行处理的位置及其位于哪个蓝图中。

  • 另一个常见的问题位置是TickWidgets更新控件

如果这个统计数据值很高,这表示您可能同时显示了太多控件,或者这些控件上的属性代理过于复杂。 一些slate属性,比如可见性,可能会在每帧被调用好几次,这样它们的值必须要小而且能及时返回。

您是不是在游戏中有很多骨架网格物体?

SkinnedMeshComp更新时间有时也会消耗很多系统资源 请尝试降低显示在分析文件中的骨架中的骨骼数量,或者降低动画蓝图的复杂度。 如果您不需要在无法看到骨架网格物体时更新动画,请考虑将骨架网格物体组件上的MeshComponentUpdateFlag网格物体组件更新标识正确设置为OnlyTickPoseWhenRendered仅在渲染时更新姿势。 请注意,将此标识设置为**AnimNotifies动画通知**将使得这些网格物体不被渲染时不再对其进行触发。

打包项目调试

可以参考打包项目的Debug方法

资产优化工具

  • MergeActors合批工具。
  • DeviceProfile针对不同设备使用不同的渲染参数。
  • LOD
    • ModelLOD
    • MaterialLOD
    • ParticleLOD
  • 粒子裁剪工具:将粒子透明部分裁剪掉,减少重叠区域。