首页 > 其他分享 >Unreal引擎启动流程及耗时分析

Unreal引擎启动流程及耗时分析

时间:2022-09-05 10:55:08浏览次数:97  
标签:FModuleManager Get TEXT Unreal 耗时 引擎 LoadModule 加载

引擎版本: 4.18

部分耗时流程结构概述:

Winmain
	└GuardedMain
		└EnginePreInit
			└FEngineLoop::PreInit
				└LoadPreInitModules()
				└AppInit()
				└ProcessNewlyLoadedUObjects()
				└LoadStartupCoreModules()
				└LoadPreLoadingScreedModules
				└LoadStartupModules()
				└FStartupPackages::LoadAll()
		└EditorInit( IEngineLoop& EngineLoop )		
        	└EngineLoop.Init()
        	└FUnrealEdMisc::Get().OnInit()
        	└MainFrameModule.CreateDefaultMainFrame()

EnginePreInit()

int32 FEngineLoop::PreInit( const TCHAR* CmdLine )
{
	// 进行一些硬件/平台相关的设置
    
    //
    LoadPreInitModules();
    // 11.10
    AppInit();
    
    ProcessNewlyLoadedUObjects();
    
    LoadStartupCoreModules();
    
    // Load up all modules that need to hook into the loading screen
	if (!IProjectManager::Get().LoadModulesForProject(ELoadingPhase::PreLoadingScreen) || !IPluginManager::Get().LoadModulesForEnabledPlugins(ELoadingPhase::PreLoadingScreen))
	{
		return 1;
	}
    
    // Load PreDefault/Default/PostDefault Modules For Project and Enabled Plugins
	if (!LoadStartupModules())
	{
		return 1;
	}
    
    // load up the seek-free startup packages
	if ( !FStartupPackages::LoadAll() )
	{
		// At least one startup package failed to load, return 1 to indicate an error
		return 1;
	}
}

FEngineLoop::PreInit()整个流程有2000+行, 所以以上代码仅为简述, 列出了一些比较耗时的步骤以及关键步骤.

AppInit()

bool FEngineLoop::AppInit()
{
	// 解析Cmd命令
    // 执行平台对应的PreInit
    
    // 加载PostConfigInit模块
	if (!IProjectManager::Get().LoadModulesForProject(ELoadingPhase::PostConfigInit) || !IPluginManager::Get().LoadModulesForEnabledPlugins(ELoadingPhase::PostConfigInit))
	{
		return false;
	}
    
    FCoreDelegates::OnInit.Broadcast();
}

该部分耗时为6~6.5s左右.

ProcessNewlyLoadedUObjects()

参考: 《InsideUE4》UObject(十)类型系统构造-再次触发

LoadStartupCoreModules()

bool FEngineLoop::LoadStartupCoreModules()
{
	FModuleManager::Get().LoadModule(TEXT("Core"));
	FModuleManager::Get().LoadModule(TEXT("Networking"));
	
	FWindowsPlatformApplicationMisc::LoadStartupModules();
	
    FModuleManager::LoadModuleChecked<IMessagingModule>("Messaging");
    
    FModuleManager::LoadModuleChecked<IMRMeshModule>("MRMesh");
    FModuleManager::LoadModuleChecked<IEditorStyleModule>("EditorStyle");
    FModuleManager::Get().LoadModule("Slate");
    FModuleManager::Get().LoadModule("SlateReflector");
    FModuleManager::Get().LoadModule("UMG");
    
    FModuleManager::Get().LoadModule("MessageLog");
	FModuleManager::Get().LoadModule("CollisionAnalyzer");
    
    FModuleManager::Get().LoadModule("FunctionalTesting");
    
    FModuleManager::Get().LoadModule(TEXT("BehaviorTreeEditor"));
	FModuleManager::Get().LoadModule(TEXT("GameplayTasksEditor"));
    
    FModuleManager::LoadModuleChecked<IAudioEditorModule>("AudioEditor")->RegisterAssetActions();
    FModuleManager::Get().LoadModule("StringTableEditor");
    
    FModuleManager::Get().LoadModule(TEXT("VREditor"));
    FModuleManager::Get().LoadModule(TEXT("EnvironmentQueryEditor"));
    FModuleManager::Get().LoadModule(TEXT("IntroTutorials"));
	FModuleManager::Get().LoadModule(TEXT("Blutility"));
    FModuleManager::Get().LoadModule(TEXT("Overlay"));
    FModuleManager::Get().LoadModule(TEXT("MediaAssets"));
    FModuleManager::Get().LoadModule(TEXT("ClothingSystemRuntime"));
    //FModuleManager::Get().LoadModule(TEXT("ClothingSystemEditor"));
    FModuleManager::Get().LoadModule(TEXT("PacketHandler"));
    
    return bSuccess;
}

该部分显式加载了一些核心模块.

裁剪估计会对核心功能产生影响.

LoadStartupModules()

bool FEngineLoop::LoadStartupModules()
{
	// Load any modules that want to be loaded before default modules are loaded up.
	if (!IProjectManager::Get().LoadModulesForProject(ELoadingPhase::PreDefault) || !IPluginManager::Get().LoadModulesForEnabledPlugins(ELoadingPhase::PreDefault))
	{
		return false;
	}

	// Load modules that are configured to load in the default phase
	if (!IProjectManager::Get().LoadModulesForProject(ELoadingPhase::Default) || !IPluginManager::Get().LoadModulesForEnabledPlugins(ELoadingPhase::Default))
	{
		return false;
	}
	
	// Load any modules that want to be loaded after default modules are loaded up.
	if (!IProjectManager::Get().LoadModulesForProject(ELoadingPhase::PostDefault) || !IPluginManager::Get().LoadModulesForEnabledPlugins(ELoadingPhase::PostDefault))
	{
		return false;
	}
	
    return true;
}

在引擎启动过程中, 相关的模块通过LoadingPhase来控制加载时机:

Name Description
EarliestPossible As soon as possible - in other words, uplugin files are loadable from a pak file (as well as right after PlatformFile is set up in case pak files aren't used) Used for plugins needed to read files (compression formats, etc)
PostConfigInit Loaded before the engine is fully initialized, immediately after the config system has been initialized.
PostSplashScreen The first screen to be rendered after system splash screen
PreEarlyLoadingScreen Loaded before coreUObject for setting up manual loading screens, used for our chunk patching system
PreLoadingScreen Loaded before the engine is fully initialized for modules that need to hook into the loading screen before it triggers
PreDefault Right before the default phase
Default Loaded at the default loading point during startup (during engine init, after game modules are loaded.)
PostDefault Right after the default phase
PostEngineInit After the engine has been initialized
None Do not automatically load this module
Max

通过日志打点可以观察到, PreDefault|Default|PostDefault这三种类型的模块在PreInit()阶段就已经加载完毕了, 而PostEngineInit类型的模块将在EditorInit()阶段加载, 除去None以外的LoadingPhase都是在编辑器加载完成前执行的, 在当前的编辑器中, 不同时机的加载耗时如下(引擎启动时间波动较大, 所以引擎加载时间此处做定性分析而非定量分析):

Name 优化前耗时(s) 优化后耗时(s) 差值(s)
PostConfigInit 0.449 0.373 0.08
PreLoadingScreen 0.319 0.272 0.05
PreDefault 2.131 4.662 -2.53
Default 25.232 17.721 7.51
PostDefault 0.125 0.120 0.00
PostEngineInit 8.075 5.813 2.26

本次引擎在PreInit()阶段耗时为68.757秒, LoadStartupModules()为27.8秒, 占40.43%, 通过观察不难发现, 一些模块/插件为仅移动平台下加载的模块, 或美术人员对模型进行优化耗时的模块, 或引擎原生但项目中未使用的模块, 可以对此处进行一些策略配置, 来减少引擎启动耗时.

EditorInit()

int32 EditorInit( IEngineLoop& EngineLoop )
{
	// 加载一些模块, 耗时8.06s
	int32 ErrorLevel = EngineLoop.Init();
    
    // 发送编辑器已启动事件: 耗时0.0s
    FEngineAnalytics::GetProvider().RecordEvent(TEXT("Editor.ProgramStarted"), EventAttributes);
    
    /** The public interface for the unreal editor misc singleton. */
    // 注册编辑器事件
    // 注册资源编辑器/材质编辑器/寻路网格/曲线命令
    // 记录操作
    // 加载一些编辑器模块,详见(FEditorModeRegister::Initialize())
    // 根据配置加载版本控制模块(P4 or Git)
    // 加载地图
    // 初始化一些构建配置
    // 绑定一些日志事件监听
    // 耗时0.72s
    FUnrealEdMisc::Get().OnInit();
    
    // 从.ini文件中读取默认路径, 用来加载与保存: 耗时0.0s
    FEditorDirectories::Get().LoadLastDirectories();
    
    // 设置actor folders单例
    FActorFolders::Init();
    // =================== CORE EDITOR INIT FINISHED ===================
    
    // 从命令行判断是否是immersive mode以设置编辑器
    
    // 显示编辑器窗口
    IMainFrameModule& MainFrameModule = FModuleManager::LoadModuleChecked<IMainFrameModule>(TEXT("MainFrame"));
    MainFrameModule.CreateDefaultMainFrame( bStartImmersive, bStartPIE );
    
    // 判断是否是VRMode, 是则加载对应编辑器: 耗时0.0s
    VREditorModule.EnableVREditor( true );
    
    // 提示是否需要更新游戏工程文件: 耗时0.0s
    FGameProjectGenerationModule::Get().CheckForOutOfDateGameProjectFile();
	FGameProjectGenerationModule::Get().CheckAndWarnProjectFilenameValid();
    
    // 在stat中打点
    // 加载HierarchicalLODOutliner模块
    
    return 0;
}

EngineLoop.Init()

int32 FEngineLoop::Init()
{
	InitTime();
    
    GEngine->Init(this);
    
	if (!IProjectManager::Get().LoadModulesForProject(ELoadingPhase::PostEngineInit) || !IPluginManager::Get().LoadModulesForEnabledPlugins(ELoadingPhase::PostEngineInit))
	{
		GIsRequestingExit = true;
		return 1;
	}
    
    GEngine->Start();
    
    // Ready to measure thread heartbeat
	FThreadHeartBeat::Get().Start();
}

FUnrealEdMisc::Get().OnInit()

该部分耗时在0.7s左右.

FEditorModeRegister::Initialize()

不同版本加载模块对比:

序号 4.18 4.27 5.0
1 PlacementMode PlacementMode
2 BspMode
3 TextureAlignMode
4 GeometryMode
5 ActorPickerMode ActorPickerMode ActorPickerMode
6 SceneDepthPickerMode SceneDepthPickerMode SceneDepthPickerMode
7 MeshPaintMode MeshPaintMode
8 LandscapeEditor LandscapeEditor LandscapeEditor
9 FoliageEdit FoliageEdit FoliageEdit
10 VirtualTexturingEditor VirtualTexturingEditor

4.18(我们项目编辑器也是这样)中有一行注释:

//@TODO: ROCKET: These are probably good plugin candidates, that shouldn't have to be force-loaded here but discovery loaded somehow

说明这里加载的Module可以在此后的某个时间段按需加载, 从4.25版本开始BspMode, TextureAlignMode, GeometryMode不在此处加载.

MainFrameModule.CreateDefaultMainFrame

该部分耗时在14s~15s左右, 主要负责创建编辑器窗口:

void FMainFrameModule::CreateDefaultMainFrame( const bool bStartImmersive, const bool bStartPIE )
{
    //...
    RootWindow->SetContent(MainFrameContent.ToSharedRef());
    
    // Initialize the main frame window
	MainFrameHandler->OnMainFrameGenerated( MainTab, RootWindow );
		
	// Show the window!
	MainFrameHandler->ShowMainFrameWindow( RootWindow, bStartImmersive, bStartPIE );
    
    MainFrameCreationFinishedEvent.Broadcast(RootWindow, ShouldShowProjectDialogAtStartup());
}

参考文章:

标签:FModuleManager,Get,TEXT,Unreal,耗时,引擎,LoadModule,加载
From: https://www.cnblogs.com/zhang-mo/p/16657313.html

相关文章

  • 为您的网站构建推荐引擎的 3 个原因
    为您的网站构建推荐引擎的3个原因如果您没有在您的网站上使用推荐引擎,那么您将错失提高参与度和转化率的关键机会。这就是为什么构建推荐引擎对于您的网站的成功至关重......
  • enjoy模板引擎
    <dependency> <groupId>com.jfinal</groupId> <artifactId>enjoy</artifactId> <version>5.0.0</version></dependency>importcom.jfinal.kit.Kv;importcom.jfina......
  • velocity模板渲染引擎
    <dependency><groupId>org.apache.velocity</groupId><artifactId>velocity-engine-core</artifactId><version>使用人数最多的版本</version></dependency>im......
  • WebGPU光追引擎基础课:课程介绍
    大家好~我开设了“WebGPU光追引擎基础课”的线上课程,从0开始,在课上带领大家现场写代码,使用WebGPU开发基础的光线追踪引擎课程重点在于基于GPU并行计算,实现BVH构建和遍历......
  • WebGPU光追引擎基础课系列目录
    大家好~我开设了“WebGPU光追引擎基础课”的线上课程,从0开始,在课上带领大家现场写代码,使用WebGPU开发基础的光线追踪引擎课程重点在于基于GPU并行计算,实现BVH构建和遍历......
  • TDengine3.0计算查询引擎的优化与升级
    在8月13日的 TDengine 开发者大会上,TDengine计算引擎架构师廖浩均带来题为《TDengine3.0——全新计算查询引擎的设计》的主题演讲,详细阐述了TDengine3.0计算查......
  • LeaRun.Java工作流引擎 快速开发业务流程
    工作流引擎是用来开发工作流转的框架。作为应用系统的一部分,能根据角色、分工和条件的不同决定信息传递路由、内容等级等核心解决方案,包含组织结构、流程、节点、转向规则......
  • smile——Java机器学习引擎
    资源https://haifengl.github.io/https://github.com/haifengl/smile介绍Smile(统计机器智能和学习引擎)是一个基于Java和Scala的快速、全面的机器学习、NLP、线性代数、......
  • 【MySQL】MariaDB使用connect存储引擎访问SQLServer中的表
    借助connect存储引擎,Mariadb可以访问任何ODBC数据源。本文是以CentOS7为例。安装的内容有:ODBCdriver,unixODBC 1.下载ODBC对应linux的驱动下载地址:https://docs.mi......
  • 前端性能优化(一)---时间角度优化:减少耗时
    一、为什么要进行性能优化对于一个产品来说,用户的体验是最重要的。当页面加载时间过长,交互操作不流畅时,会给用户带来很糟糕的体验,会导致用户流失。二、前端常见的性能优......