// Copyright Epic Games, Inc. All Rights Reserved. #include "MemoryAnalysis.h" #include "AnalysisServicePrivate.h" #include "Common/Utils.h" #include "HAL/LowLevelMemTracker.h" namespace TraceServices { FMemoryAnalyzer::FMemoryAnalyzer(IAnalysisSession& InSession, FMemoryProvider* InProvider) : Session(InSession) , Provider(InProvider) { check(Provider != nullptr); } FMemoryAnalyzer::~FMemoryAnalyzer() { } void FMemoryAnalyzer::OnAnalysisBegin(const FOnAnalysisContext& Context) { auto& Builder = Context.InterfaceBuilder; Builder.RouteEvent(RouteId_TagsSpec, "LLM", "TagsSpec"); Builder.RouteEvent(RouteId_TrackerSpec, "LLM", "TrackerSpec"); Builder.RouteEvent(RouteId_TagSetSpec, "LLM", "TagSetSpec"); // added in UE 5.6 Builder.RouteEvent(RouteId_TagValue, "LLM", "TagValue"); } void FMemoryAnalyzer::OnAnalysisEnd() { if (Provider) { FProviderEditScopeLock _(*Provider); Provider->OnAnalysisCompleted(); } } bool FMemoryAnalyzer::OnEvent(uint16 RouteId, EStyle Style, const FOnEventContext& Context) { if (!Provider) { return false; } LLM_SCOPE_BYNAME(TEXT("Insights/FMemoryAnalyzer")); const auto& EventData = Context.EventData; switch (RouteId) { case RouteId_TagsSpec: { const int64 TagId = EventData.GetValue("TagId"); const int64 ParentId = EventData.GetValue("ParentId"); const uint8 TagSetId = EventData.GetValue("TagSetId"); // added in UE 5.6 FString Name = FTraceAnalyzerUtils::LegacyAttachmentString("Name", Context); FProviderEditScopeLock _(*Provider); Provider->AddTagSpec(TagId, Name, ParentId, (FMemoryTagSetId)TagSetId); } break; case RouteId_TrackerSpec: { uint8 TrackerId = EventData.GetValue("TrackerId"); FString Name = FTraceAnalyzerUtils::LegacyAttachmentString("Name", Context); FProviderEditScopeLock _(*Provider); Provider->AddTrackerSpec((FMemoryTrackerId)TrackerId, Name); } break; case RouteId_TagSetSpec: // added in UE 5.6 { const uint8 TagSetId = EventData.GetValue("TagSetId"); FString Name; EventData.GetString("Name", Name); FProviderEditScopeLock _(*Provider); Provider->AddTagSetSpec((FMemoryTagSetId)TagSetId, Name); } break; case RouteId_TagValue: { const uint8 TrackerId = EventData.GetValue("TrackerId"); const uint64 Cycle = EventData.GetValue("Cycle"); const double Time = Context.EventTime.AsSeconds(Cycle); const TArrayReader& Tags = EventData.GetArray("Tags"); // was traced as (void*)[] const TArrayReader& Samples = EventData.GetArray("Values"); const uint32 TagsCount = Tags.Num(); const int64* TagsData = Tags.GetData(); TArray TagsCopy; if (TagsData == nullptr) { // For backward compatibility with 32bit platforms. const TArrayReader& Tags32 = EventData.GetArray("Tags"); check(Tags32.Num() == TagsCount); const uint32* TagsData32 = Tags32.GetData(); if (!TagsData32) { break; } TagsCopy.Reserve(TagsCount); for (uint32 TagIndex = 0; TagIndex < TagsCount; ++TagIndex) { TagsCopy.Push(TagsData32[TagIndex]); } TagsData = TagsCopy.GetData(); } check(Samples.Num() == TagsCount); const int64* SamplesData = Samples.GetData(); check(SamplesData != nullptr); TArray Values; Values.Reserve(TagsCount); for (uint32 TagIndex = 0; TagIndex < TagsCount; ++TagIndex) { Values.Push(FMemoryTagSample{ SamplesData[TagIndex] }); } Sample++; { FProviderEditScopeLock _(*Provider); Provider->AddTagSnapshot(TrackerId, Time, TagsData, Values.GetData(), TagsCount); } { FAnalysisSessionEditScope _(Session); Session.UpdateDurationSeconds(Time); } } break; } return true; } } // namespace TraceServices