// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "Templates/SharedPointer.h" #include "Trace/Analyzer.h" #include "AnalysisServicePrivate.h" #include "Model/LoadTimeProfilerPrivate.h" namespace TraceServices { struct FClassInfo; inline bool operator!=(const FLoadTimeProfilerCpuEvent& Lhs, const FLoadTimeProfilerCpuEvent& Rhs) { return Lhs.Package != Rhs.Package || Lhs.Export != Rhs.Export || Lhs.EventType != Rhs.EventType; } class FAsyncLoadingTraceAnalyzer : public UE::Trace::IAnalyzer { public: FAsyncLoadingTraceAnalyzer(IAnalysisSession& Session, FLoadTimeProfilerProvider& LoadTimeProfilerProvider); virtual ~FAsyncLoadingTraceAnalyzer(); virtual void OnAnalysisBegin(const FOnAnalysisContext& Context) override; virtual void OnAnalysisEnd() override; virtual bool OnEvent(uint16 RouteId, EStyle Style, const FOnEventContext& Context) override; private: struct FRequestState; struct FAsyncPackageState; struct FLinkerLoadState; struct FRequestGroupState { FString Name; TArray Requests; FLoadRequest* LoadRequest = nullptr; uint64 LatestEndCycle = 0; uint64 ActiveRequestsCount = 0; }; struct FRequestState { uint64 WallTimeStartCycle; uint64 WallTimeEndCycle; uint32 ThreadId; TSharedPtr Group; TArray AsyncPackages; }; struct FAsyncPackageState { FPackageInfo* PackageInfo = nullptr; FRequestState* Request = nullptr; FLinkerLoadState* Linker = nullptr; TSet ImportedAsyncPackages; TSet ImportedByAsyncPackages; }; struct FLinkerLoadState { FPackageInfo* PackageInfo = nullptr; FAsyncPackageState* AsyncPackage = nullptr; bool bHasFakeAsyncPackageState = false; }; struct FScopeStackEntry { FLoadTimeProfilerCpuEvent Event; bool EnteredEvent; }; struct FThreadState { FScopeStackEntry CpuScopeStack[256]; uint64 CpuScopeStackDepth = 0; int64 PostLoadScopeDepth = 0; FLoadTimeProfilerCpuEvent CurrentEvent; TArray> RequestGroupStack; FLoadTimeProfilerProvider::CpuTimelineInternal* CpuTimeline; void EnterScope(double Time, const FPackageInfo* PackageInfo); void EnterScope(double Time, const FPackageExportInfo* ExportInfo, ELoadTimeProfilerObjectEventType EventType); void LeaveScope(double Time); ELoadTimeProfilerObjectEventType GetCurrentScopeEventType(); FPackageExportInfo* GetCurrentExportScope(); }; void PackageRequestAssociation(const FOnEventContext& Context, FAsyncPackageState* AsyncPackageState, FRequestState* RequestState); FThreadState& GetThreadState(uint32 ThreadId); const FClassInfo* GetClassInfo(uint64 ClassPtr) const; enum : uint16 { RouteId_StartAsyncLoading, RouteId_SuspendAsyncLoading, RouteId_ResumeAsyncLoading, RouteId_NewAsyncPackage, RouteId_DestroyAsyncPackage, RouteId_NewLinker, RouteId_DestroyLinker, RouteId_BeginRequest, RouteId_EndRequest, RouteId_BeginRequestGroup, RouteId_EndRequestGroup, RouteId_PackageSummary, RouteId_AsyncPackageRequestAssociation, RouteId_AsyncPackageLinkerAssociation, RouteId_AsyncPackageImportDependency, RouteId_BeginProcessSummary, RouteId_EndProcessSummary, RouteId_BeginCreateExport, RouteId_EndCreateExport, RouteId_BeginSerializeExport, RouteId_EndSerializeExport, RouteId_BeginPostLoad, RouteId_EndPostLoad, RouteId_BeginPostLoadObject, RouteId_EndPostLoadObject, RouteId_ClassInfo, RouteId_BatchIssued, RouteId_BatchResolved, // Backwards compatibility RouteId_BeginObjectScope, RouteId_EndObjectScope, RouteId_BeginPostLoadExport, RouteId_EndPostLoadExport, }; enum { FormatBufferSize = 65536 }; TCHAR FormatBuffer[FormatBufferSize]; TCHAR TempBuffer[FormatBufferSize]; IAnalysisSession& Session; FLoadTimeProfilerProvider& LoadTimeProfilerProvider; template struct FPointerMapKeyFuncs { typedef uint64 KeyType; typedef uint64 KeyInitType; typedef const TPairInitializer& ElementInitType; enum { bAllowDuplicateKeys = false }; static FORCEINLINE bool Matches(uint64 A, uint64 B) { return A == B; } static FORCEINLINE uint32 GetKeyHash(uint64 Key) { return PointerHash((const void*)Key); } static FORCEINLINE KeyInitType GetSetKey(ElementInitType Element) { return Element.Key; } }; template using TPointerMap = TMap>; TPointerMap ActiveAsyncPackagesMap; TPointerMap ActiveLinkersMap; TPointerMap ExportsMap; TMap ActiveRequestsMap; TArray FakeRequestsStack; TPointerMap ActiveBatchesMap; TMap ThreadStatesMap; TPointerMap ClassInfosMap; FPackageInfo* UnknownPackageInfo = nullptr; uint64 ErrorCount = 0; uint64 WarningCount = 0; }; } // namespace TraceServices