UE4性能优化:PGO与LTO编译器级优化实战指南

发布时间:2026/7/12 14:00:10
UE4性能优化:PGO与LTO编译器级优化实战指南 1. 项目概述当UE4项目性能遇到瓶颈时做UE4项目尤其是移动端或者对帧率要求极高的项目性能优化是个绕不开的坎。很多时候我们绞尽脑汁地优化蓝图逻辑、合并Draw Call、压缩贴图甚至重构C代码。但有没有一种方法能在不修改一行现有代码的情况下就让整个项目的运行效率再上一个台阶答案是肯定的这就是今天要深入探讨的两种编译器级别的优化技术PGOProfile-Guided Optimization配置文件引导优化和LTOLink Time Optimization链接时优化。对于很多从Unity转过来或者主要使用蓝图开发的开发者来说这两个词可能有点陌生。它们不像调整一个材质参数或者优化一个粒子系统那样直观而是作用于项目编译生成最终可执行文件.exe, .apk, .ipa的“幕后”阶段。简单来说你可以把它们理解为一种“智能编译”模式。编译器比如Visual Studio里的MSVC或者Xcode里的Clang在生成代码时不再是机械地按部就班而是会根据程序实际运行时的“热点”数据PGO或者拥有全局的视野进行跨模块优化LTO从而生成更高效、更紧凑的机器码。为什么这对UE4项目特别重要因为UE4引擎本身就是一个庞然大物加上我们自己的游戏逻辑最终生成的二进制文件包含了海量的函数和代码路径。传统的编译优化如/O2只在单个编译单元.cpp文件内生效编译器看不到其他.cpp文件里的函数是怎么被调用的。这就好比让一群顶尖工匠各自闭门造车虽然每个零件都打磨得极好但组装起来可能因为接口不匹配或流程冗余而效率低下。LTO解决了“组装”时的全局优化问题。而PGO则更进一步它不再是“猜测”哪些代码路径更常用而是通过实际运行一次程序收集真实的性能分析数据Profile告诉编译器“看这个函数被调用了上百万次那个分支几乎从来没走过。” 编译器拿到这份“实战报告”后在下一次编译时就能做出极其精准的优化决策比如将高频函数内联、对关键循环进行向量化、调整分支预测、甚至重新排列代码段以改善CPU缓存命中率。在移动端性能优化压力巨大的今天或者是在开发PC/主机平台追求极限帧率的竞技类游戏时启用PGO和LTO带来的性能提升往往是“免费”的——你不需要重写核心算法只需要改变一下编译流程。根据项目规模和代码结构的不同整体性能提升可以达到5%到15%甚至在某些特定场景下更高。这相当于白捡了十几帧其价值不言而喻。接下来我们就抛开理论直接进入实战一步步拆解如何在UE4项目中配置和使用这两项“黑科技”。2. 核心原理与方案选型为什么是PGOLTO在决定动手之前我们必须先搞清楚这两项技术到底在做什么以及它们如何互补。知其然更要知其所以然这样才能在遇到问题时心中有数而不是盲目地套用配置。2.1 PGO配置文件引导优化的三步舞曲PGO不是一个单一的开关而是一个分为三个阶段的流程插桩Instrument、训练Train和应用Use。我们可以把它想象成训练一个AI模型。第一阶段插桩编译。在这个阶段我们告诉编译器“请你先别急着优化而是往生成的代码里插入一些小小的‘探针’。” 这些探针非常轻量它们的作用是在程序运行时默默记录下每个函数被调用了多少次、每个代码分支走向了哪一边、哪些循环是热点。用UE4的术语来说我们这时编译出的不是一个用于分发给玩家的版本而是一个专门用于收集数据的“分析版”可执行文件。这个文件会比正常版本稍大、稍慢因为它包含了所有探针逻辑。第二阶段运行训练生成Profile文件。接下来我们需要运行这个“分析版”的程序并且要尽可能地模拟真实玩家的行为。对于游戏项目这意味着你需要运行一系列有代表性的场景从启动画面到主菜单进入一个标准关卡进行一段时间的游戏包括战斗、探索、载具驾驶等核心玩法最后退出。这个过程的目标是让探针收集到能够反映真实使用情况的样本数据。运行结束后这些数据会被写入一个或多个.pgcProfile-Guided Count文件。最后我们需要使用一个微软提供的工具pgomgr.exe或xperf对于新版MSVC将这些零散的.pgc文件合并成一个最终的.pgdProfile-Guided Database文件。这个.pgd文件就是我们的“黄金数据集”它浓缩了程序运行时的行为特征。第三阶段引导优化编译。现在我们拿着这份珍贵的.pgd文件重新进行编译。这一次我们告诉编译器“请开启最高级别的优化如/O2或/Ox并且参考这个Profile文件来指导你的优化决策。” 编译器会仔细分析.pgd中的数据做出诸如将高频调用的函数强制内联以减少调用开销将频繁执行的热点代码段安排在内存中相邻的位置提升CPU缓存效率对几乎从不执行的分支代码进行“冷处理”甚至将其移到代码段末尾减少对指令缓存行的污染。经过这个阶段编译出来的才是最终交付给玩家的、经过深度优化的高性能版本。注意PGO的优化效果极度依赖于训练数据的质量。如果你的训练场景覆盖不全比如只跑了主菜单没进关卡那么编译器可能会做出错误的优化比如把实际游戏中频繁使用的函数判断为“冷代码”而不予优化甚至可能导致性能下降。因此设计一套全面、自动化的训练流程是PGO成功的关键。2.2 LTO链接时优化的上帝视角如果说PGO是依靠“实战数据”来指导优化那么LTO就是给编译器赋予了“上帝视角”。在传统的编译-链接过程中编译器一次只能看到一个.cpp文件经过头文件展开后称为一个编译单元。它在这个单元内部可以尽情优化比如把一些小函数内联掉。但是一旦涉及到调用另一个.cpp文件里的函数编译器就只能看到一个函数声明在头文件里它不知道那个函数的实现细节因此很多优化手段比如跨函数的内联、跨模块的常量传播、死代码消除就无法进行。LTO彻底改变了这个流程。当启用LTO在MSVC中对应/GL编译选项和/LTCG链接选项时编译器不会立即生成传统的目标文件.obj而是生成一种包含中间语言如LLVM IR的特殊文件。等到链接器Linker工作时它不再是简单地把一堆.obj拼在一起而是把所有这些中间表示文件都“吞”进去在一个全局的上下文中进行优化。这时链接器能看到整个程序的所有代码它可以将某个.cpp里的小函数内联到另一个.cpp的调用处彻底消除函数调用开销。如果发现某个函数在整个程序中都没有被调用即使它在各自的.obj里没有被标记为死代码链接器也可以安全地将其删除。进行跨模块的常量传播和公共子表达式消除。这对于UE4这样模块化程度极高的引擎尤其有益。引擎模块、插件模块、游戏模块之间的函数调用壁垒被打破可以产生显著的二进制文件体积缩减和运行时性能提升。2.3 为何在UE4中结合使用PGO和LTO是绝配。我们可以这样理解它们的协作关系LTO先行打好基础LTO首先进行全局的、基于代码静态分析的优化。它重新组织代码布局内联跨模块函数为整个程序建立一个更优的底层结构。PGO后置精准打击在LTO优化后的“优质代码”基础上再运行PGO训练。这时收集到的Profile数据反映的是经过LTO初步优化后的程序行为更加精准。然后PGO再根据这份数据进行第二轮基于运行时特征的微调优化例如根据实际执行频率调整分支预测提示、对热点循环进行向量化等。这个组合拳的效果是112的。通常的实践流程是在开发阶段为了快速的迭代编译我们只开启LTO因为PGO需要额外的训练步骤比较耗时。而在为发布平台如App Store、Google Play、Steam构建最终的分发包时我们才会完整地执行PGO的三步流程并且是在已经开启LTO的基础上进行以榨取最后一滴性能潜力。3. 实战环境配置与编译流程改造理论讲完了我们进入硬核实操环节。这里以最常用的Windows平台、Visual Studio和UE4.26/4.27版本为例进行说明。其他平台如Linux/macOS和UE5的流程在概念上相通但具体命令和文件路径有所不同。3.1 启用LTO链接时优化在UE4中启用LTO相对简单主要是通过修改构建配置参数来实现。3.1.1 修改项目构建文件找到你的游戏项目根目录下的.Target.cs文件例如MyGame.Target.cs。我们需要在GlobalCompileEnvironment和GlobalLinkEnvironment中为发布Shipping配置添加LTO标志。// MyGame.Target.cs 或 MyGameEditor.Target.cs (通常修改前者) using UnrealBuildTool; using System.Collections.Generic; public class MyGameTarget : TargetRules { public MyGameTarget(TargetInfo Target) : base(Target) { Type TargetType.Game; DefaultBuildSettings BuildSettingsVersion.V2; ExtraModuleNames.AddRange(new string[] { MyGame }); // 在构造函数中添加针对Shipping版本的LTO配置 if (Target.Configuration UnrealTargetConfiguration.Shipping) { bUseUnityBuild false; // 可选关闭Unity Build以获得更精确的LTO但编译速度会变慢 bUsePCHFiles false; // 可选关闭PCH以配合某些LTO场景非必需 // 关键启用链接时代码生成LTCG这是MSVC对LTO的称呼 AdditionalCompilerArguments.Add(/GL); AdditionalLinkerArguments.Add(/LTCG); } } }参数解释/GL 告知编译器生成支持全程序优化的目标文件即中间语言格式而非传统.obj。/LTCG 告知链接器在链接阶段执行链接时代码生成即进行全局优化。bUseUnityBuild false Unity Build又称单编译单元构建会将多个.cpp文件合并成一个大的编译单元来加速编译。但这会干扰LTO因为LTO依赖于独立的编译单元信息来进行跨模块优化。关闭它能获得更好的LTO效果但会显著增加编译时间需要权衡。bUsePCHFiles false 预编译头文件有时会与/GL产生冲突。如果编译时遇到奇怪错误可以尝试关闭PCH。3.1.2 在Visual Studio中验证生成Visual Studio项目文件后用VS打开解决方案。右键点击你的游戏项目选择“属性”。在“配置属性” - “C/C” - “优化”下查看“全程序优化”是否设置为“使用链接时代码生成 (/GL)”。在“链接器” - “优化”下查看“启用链接时代码生成”是否设置为“是 (/LTCG)”。这应该与你代码中的设置一致。实操心得第一次为大型UE4项目启用LTO时链接Linking阶段可能会非常漫长并且内存消耗巨大建议至少32GB内存。这是正常的因为链接器正在处理整个程序的中间表示。此外确保你的Visual Studio安装了最新的VC工具集新版工具集对LTO的支持和效率更好。3.2 配置PGO配置文件引导优化PGO的配置更为复杂因为它涉及一个多步骤的流水线。UE4本身没有提供一键式的PGO支持我们需要手动修改构建脚本或利用构建系统如Jenkins, TeamCity来编排这个流程。3.2.1 第一阶段插桩编译首先我们需要创建一个特殊的“插桩”构建配置。通常我们基于Shipping配置进行修改但定义一个独立的PGOInstrument配置更清晰。在.Target.cs文件中我们可以通过判断一个自定义的全局变量或编译环境变量来切换配置。// 在TargetRules构造函数中 bool bBuildingForPGOInstrument false; // 可以通过读取环境变量来判断例如 // string envPGO Environment.GetEnvironmentVariable(UE4_PGO_PHASE); // bBuildingForPGOInstrument (envPGO INSTRUMENT); if (Target.Configuration UnrealTargetConfiguration.Shipping || bBuildingForPGOInstrument) { // 公共的Shipping配置包括LTO AdditionalCompilerArguments.Add(/GL); AdditionalLinkerArguments.Add(/LTCG); if (bBuildingForPGOInstrument) { // PGO 插桩阶段特定设置 // 1. 添加插桩编译标志 AdditionalCompilerArguments.Add(/GL /Gy /Zi); // /Gy 启用函数级链接便于插桩 // 关键告诉编译器我们处于PGO插桩阶段 AdditionalCompilerArguments.Add(/fprofile-generate); // 2. 指定生成的PGD文件路径可选编译器有默认位置 // AdditionalLinkerArguments.Add(/fprofile-generate\PGOData\\MyGame.pgd\); // 3. 链接器也需要对应标志 AdditionalLinkerArguments.Add(/LTCG:PGINSTRUMENT); // 注意/LTCG:PGINSTRUMENT 与 /fprofile-generate 需配合使用。 } else { // 这是最终的Shipping构建应用优化阶段我们稍后配置 // 此时先保持为空或添加最终阶段的标志见下文 } }更实际的做法是不修改.Target.cs而是通过直接传递参数给UBTUnreal Build Tool和编译器。我们可以创建一个批处理脚本BuildPGO.bat来管理整个流程。3.2.2 编写PGO构建与管理脚本下面是一个简化但可用的Windows批处理脚本示例展示了PGO的三个阶段echo off setlocal enabledelayedexpansion set PROJECT_NAMEMyGame set UE4ROOTD:\UE_4.27 set CONFIGShipping set PLATFORMWin64 echo Phase 1: Instrumented Build REM 清理旧文件确保从干净状态开始 rd /s /q %UE4ROOT%\%PROJECT_NAME%\Saved\Profiling\PGO 2nul REM 调用UBT进行插桩编译。关键是通过 -pgoinstrument 参数UE4.26支持或直接传递编译器参数。 REM 方法A如果引擎版本支持需检查源码中是否有此参数 %UE4ROOT%\Engine\Build\BatchFiles\Build.bat %PROJECT_NAME%Editor %PLATFORM% %CONFIG% -pgoinstrument -waitmutex -clean REM 方法B更通用的方法通过环境变量传递编译器标志需要修改BuildConfiguration.xml或直接修改Target.cs响应环境变量 REM set CL/fprofile-generate REM set LINK/LTCG:PGINSTRUMENT REM %UE4ROOT%\Engine\Build\BatchFiles\Build.bat %PROJECT_NAME%Editor %PLATFORM% %CONFIG% -waitmutex if errorlevel 1 ( echo Instrumented build failed! pause exit /b 1 ) echo Phase 2: Training Run REM 找到刚编译出的插桩版可执行文件 set INSTRUMENTED_EXE%UE4ROOT%\%PROJECT_NAME%\Binaries\%PLATFORM%\%PROJECT_NAME%-%PLATFORM%-%CONFIG%.exe REM 运行游戏进行训练。这里需要你有一套自动化的测试流程。 REM 例如启动游戏自动加载一个测试关卡运行一段时间后退出。 REM 你可以编写一个简单的控制台命令脚本或使用UE4的自动化系统Automation。 echo Launching instrumented executable for training... REM 模拟运行这里只是示例。实际中你需要运行足够长的时间覆盖各种游戏场景。 start /wait %INSTRUMENTED_EXE% -ExecCmdsopen /Game/Maps/YourTrainingMap; quit -log -unattended -nopause REM 多次运行合并数据可以使Profile更稳定 REM %INSTRUMENTED_EXE% -ExecCmdsopen /Game/Maps/AnotherMap; quit -log -unattended -nopause echo Phase 3: Merge Profile Data REM 训练运行后会在可执行文件同级目录生成 .pgc 文件。 REM 使用微软的 pgomgr.exe (位于VC工具目录) 合并 .pgc 为 .pgd set VCINSTALLDIRC:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\bin\Hostx64\x64 set PGO_DIR%UE4ROOT%\%PROJECT_NAME%\Binaries\%PLATFORM% %VCINSTALLDIR%\pgomgr.exe /merge %PGO_DIR%\*.pgc %PGO_DIR%\%PROJECT_NAME%.pgd echo Phase 4: Optimized Build Using Profile REM 清理之前的输出准备最终构建 rd /s /q %UE4ROOT%\%PROJECT_NAME%\Binaries 2nul rd /s /q %UE4ROOT%\%PROJECT_NAME%\Intermediate 2nul REM 设置环境变量指示Target.cs进入PGO优化阶段或者直接传递参数 REM 关键使用 /fprofile-use 和 /LTCG:PGOPTIMIZE 标志 set CL/fprofile-use%PGO_DIR%\%PROJECT_NAME%.pgd set LINK/LTCG:PGOPTIMIZE REM 调用UBT进行最终优化构建 %UE4ROOT%\Engine\Build\BatchFiles\Build.bat %PROJECT_NAME%Editor %PLATFORM% %CONFIG% -waitmutex if errorlevel 1 ( echo Optimized build failed! pause exit /b 1 ) echo PGO Build Process Completed! pause这个脚本勾勒出了完整的流程。其中最具挑战性的是第二阶段Training Run。你需要设计一套能够充分锻炼游戏所有核心代码路径的自动化测试。对于UE4项目可以考虑使用-ExecCmds参数在启动时执行控制台命令自动加载不同地图。利用UE4的自动化测试框架Automation Driver编写模拟玩家输入移动、射击、交互的测试用例。录制一段真实的游戏过程使用引擎的Demo录制功能然后通过-playdemo命令进行回放来收集数据。重要提示训练数据的质量直接决定优化效果。一个糟糕的训练比如只停留在主菜单可能导致编译器优化了不常用的代码反而使常用路径性能下降。务必确保训练覆盖所有关键玩法循环。4. 移动端与多平台的特殊考量将PGO和LTO应用到Android或iOS平台原理相同但工具链和步骤有差异。4.1 Android (使用Android Toolchain)对于AndroidUE4使用Clang编译器。Clang同样支持PGO有时称为CSPGO或AutoFDO和LTO通过-flto标志。4.1.1 启用LTO在项目的Build.cs文件或构建脚本中为Android的Shipping配置添加额外的编译和链接标志。# 在构建脚本或UPLUnreal Plugin Language中设置 AdditionalCompilerArguments.Add(-fltothin); // 推荐使用ThinLTO平衡优化效果和链接时间 AdditionalLinkerArguments.Add(-fltothin);-fltothinThinLTO是Clang的一种增量式LTO它比全量LTO-fltofull链接更快内存占用更少同时仍能实现大部分跨模块优化非常适合大型项目。4.1.2 配置PGOClang的PGO流程也分为插桩、运行、优化三步。插桩编译添加-fprofile-generate标志。运行训练在目标设备或模拟器上运行插桩版的APK使用自动化测试脚本覆盖场景。运行后会在设备上生成.profraw文件。数据合并与优化将.profraw文件拉取到开发机使用llvm-profdata merge命令合并成.profdata文件。然后使用-fprofile-usepath_to_profdata标志进行最终优化编译。UE4的Android构建系统没有原生集成PGO流程你需要通过修改AndroidToolChain.cs或创建自定义的UPL插件来注入这些编译器标志并编写脚本自动化处理.profraw文件的拉取和合并。4.2 iOS (使用Xcode Toolchain)iOS平台使用Xcode的Clang编译器其PGO支持称为“基于样本的配置文件优化”与Android类似。4.2.1 在Xcode中配置为插桩创建新的Scheme复制一份Release scheme命名为“MyGame PGO Instrument”。设置插桩编译选项在该Scheme的Build Settings中找到“Apple Clang - Code Generation”下的“Generate Profile Code”设置为“Yes”。运行训练使用这个Scheme将游戏部署到设备上进行充分的自动化或手动游戏测试。获取Profile数据测试完成后在Xcode的“Product”菜单下选择“Show Build Folder in Finder”在对应的派生数据目录中寻找.profraw文件。或者代码运行时会将数据写入一个默认位置需要你编写脚本从设备上获取。优化编译创建另一个Scheme “MyGame PGO Optimize”在Build Settings中将“Use Profile Code”设置为“Yes”并指定上一步生成的.profdata文件路径。4.2.2 在UE4自动构建中集成对于自动化构建系统如Jenkins你需要通过命令行调用xcodebuild并传递相应的GCC_GENERATE_PROFILING_CODE和GCC_USE_PROFILING_CODE参数。同样需要编写脚本自动化整个数据收集和文件传递流程。移动端PGO的挑战移动设备上的训练环境更难控制电量、发热、后台进程。确保训练时设备处于性能模式并关闭不必要的应用。由于移动GPU和CPU架构多样在一个设备上收集的Profile数据可能不完全适用于其他设备尤其是不同SoC厂商但通常仍能带来显著的正面收益。5. 常见问题、性能对比与排查技巧启用PGO和LTO并非一帆风顺你可能会遇到各种编译错误、链接错误或运行时问题。以下是一些常见坑点及解决方案。5.1 编译与链接阶段问题问题1链接时间极长内存耗尽Out of Memory。原因全量LTO尤其是MSVC的/LTCG在处理像UE4这样的大型项目时需要将所有中间代码载入内存进行全局分析消耗巨大。解决方案增加物理内存建议至少32GB64GB或以上更佳。使用并行链接确保链接器设置中启用了“并行链接”/LTCG:PGOPTIMIZE已隐含此功能。在强大的多核机器上可以尝试设置环境变量_NO_DEBUG_HEAP1来减少调试堆对内存的占用。尝试ThinLTOClang或/LTCG:INCREMENTALMSVC实验性这些是增量或“瘦身”版LTO牺牲少量优化潜力换取更快的链接速度和更低的内存占用。对于UE4在MSVC上使用/LTCG:INCREMENTAL可能不太稳定需谨慎测试。问题2编译错误 “C1041: 无法打开程序数据库...” 或 “LNK1318: 意外的 PDB 错误”。原因PGO插桩阶段或LTO阶段生成了特殊的程序数据库PDB文件多个编译进程可能尝试同时写入同一个PDB文件导致冲突。这在并行编译/MP时尤其常见。解决方案禁用并行编译在PGO构建的特定阶段暂时在UBT命令行中添加-DisableUnityBuild -NoPCH这本身会禁用一些并行化或尝试修改BuildConfiguration.xml中的ParallelExecutor设置。但这会大幅增加编译时间。更可行的方法确保你的PGO构建脚本是串行执行的并且在每个阶段之间清理-clean中间目录和输出目录避免残留文件干扰。问题3生成的优化版程序崩溃或行为异常。原因“训练不足”或“训练偏差”。如果Profile数据没有覆盖到某些代码路径编译器可能会错误地判断某个分支永远不会执行从而过度优化甚至删除必要的代码。解决方案丰富训练场景这是根本。确保你的自动化测试覆盖所有类型的关卡、角色状态、武器系统、UI流程等。可以考虑将QA团队的测试用例自动化。合并多个Profile运行多次训练每次侧重不同玩法如一次专注战斗一次专注探索然后使用pgomgr /merge将多个.pgc文件合并成一个更具代表性的.pgd文件。保留调试符号在最终优化构建时不要完全剥离调试信息在MSVC中保留/DEBUG链接器选项但选择“生成调试信息为/DEBUG:FASTLINK”。这样当崩溃发生时你仍然能获得有意义的调用堆栈帮助定位是否是PGO导致的错误优化。5.2 性能对比方法论如何量化PGOLTO带来的收益不能只凭“感觉”需要科学测量。确立基准首先构建一个标准的、未开启PGO和LTO的Shipping版本作为性能基准Base。构建对比版本版本A仅开启LTO的Shipping版本。版本B开启LTO并应用了高质量PGO的Shipping版本。测试场景选择3-5个有代表性的性能测试场景场景1GPU瓶颈拥有大量角色和复杂特效的战斗场景。场景2CPU游戏线程瓶颈有大量AI单位进行决策和寻路的场景。场景3CPU渲染线程瓶颈视野内有大量动态物体需要剔除和提交的场景。场景4流送与加载在开放世界中高速移动触发大量资源流送的场景。收集数据在每个场景中使用UE4内置的统计命令stat unit,stat scenerendering或第三方性能分析工具如RenderDoc, Intel GPA, PIX收集关键数据平均帧时间ms与帧率FPS。游戏线程、渲染线程、GPU的耗时。Draw Call数量、三角面数量用于验证优化未改变渲染行为。内存占用物理内存、显存。分析结果预期收益LTO通常会带来小幅度的整体性能提升1%-5%和可执行文件体积减小。PGO则可能带来更显著的、不均衡的提升某些CPU密集型函数可能提升10%以上。关注点不仅要看平均帧率更要看最低帧率1% Low, 0.1% LowPGO通过改善代码局部性对减少卡顿的贡献可能比提升平均帧率更大。回归测试确保优化后的版本在所有功能测试中表现正常没有引入逻辑错误。5.3 高级技巧与注意事项增量PGO对于持续开发的项目每次小改动后都重新进行完整的PGO训练耗时太长。可以考虑“增量PGO”策略以之前稳定版本生成的.pgd文件为基础只对新修改的代码进行小范围的训练和Profile数据更新然后合并到主Profile中。但这需要更精细的构建脚本控制。分布式训练为了获得更全面的Profile数据可以在多台不同配置的机器上运行训练收集各自的.pgc文件最后合并。这有助于抵消单机硬件特性带来的偏差。与引擎源码编译结合如果你是自己编译的UE4引擎可以对引擎本身也应用PGO和LTO这能带来额外的性能红利。但这需要管理两套Profile数据引擎和游戏复杂度更高。版本控制将最终用于发布构建的.pgd文件纳入版本控制系统。这样任何团队成员都可以基于同一份经过验证的Profile数据来构建性能一致的发布版本。启用PGO和LTO就像是为你的UE4项目请了一位顶级的“二进制代码整形师”。它不改变你的游戏设计却能让相同的代码跑得更快。虽然初始的搭建和训练流程需要一些投入但对于追求极致性能的项目来说这份投入的回报是清晰且可观的。尤其是在移动平台和竞争激烈的PC/主机市场这额外的百分之几到十几的性能可能就是流畅与卡顿、成功与失败之间的那道分水岭。