Hi,
In general, we track memory allocated during asset loading (see Engine\Source\Runtime\CoreUObject\Private\Serialization\AsyncLoading.cpp and AsyncLoading2.cpp) using scoped macros like:
LLM_SCOPE_DYNAMIC_STAT_OBJECTPATH(Object->GetPackage(), ELLMTagSet::Assets); LLM_SCOPE_DYNAMIC_STAT_OBJECTPATH(Object->GetClass(), ELLMTagSet::AssetClasses); UE_TRACE_METADATA_SCOPE_ASSET_FNAME(Object->GetFName(), Object->GetClass()->GetFName(), Object->GetPackage()->GetFName());
These scopes are added in pairs (LLM_* + UE_TRACE_*) in order for both memory tracking systems to track similar data:
- the UE_TRACE_* macros are used by the “memory tracing” (i.e. “-trace=memalloc,metadata,assetmetadata”; data is exposed in Insights UI by Memory Insights / Memory Investigation queries);
- the LLM_SCOPE_* macros are used by LLM (Low Level Memory Tracker); Note that LLM data is also available to tracing / Insights using “-trace=memtag” (data is exposed in Insights UI by the new Memory Insights / Memory Tags panel, in UE 5.6).
Both “memalloc” and “memtag” channels are enabled by the “memory” channel preset, so when “-trace=memory,metadata,assetmetadata” is used, Memory Insights will show data from both memory tracking systems.
LLM mostly tracks the package names of the UObject assets, into the “Assets” tag set.
Memory tracing is trying to capture both asset (object) name and the package name.
All allocations happening during an asset loading scope are associated with the respective asset/class/package name.
But, a lot of memory is allocated outside of “asset loading” code. Even if these allocations are not really specific to an actual asset, we have used same macros to give more info to them.
For example, many allocations happening for RHI buffers and resources are also scoped with these macros. In these case, the “Asset”/“ClassName”/“Package” are not actual asset/class/package names, but RHI specific buffer names or other debug names.
Another example is Engine\Source\Runtime\Core\Private\Misc\ConfigCacheIni.cpp, where the “Asset”/“Package” is just the the config file name and the class name is specified as “ConfigFile”.
So, you need to use together info from all 3 columns (“Asset”, “ClassName”, “Package”) to figure out what are the “assets”. In the Allocs Table tree view, there are custom presets like “Asset (Package)” and “Class Name” that can be used to quickly setup groupings for these three columns.
The “loadtime”/“assetloadtime” trace channels and the “-statnamedevents” command line parameter are only used to track CPU performance of asset loading. The data tracked when these are enabled is not used in any way by the Memory Insights. Still, these can be useful just as context info (to correlate the Memory Insights timelines with CPU tracks).
- The “-statnamedevents” command line parameter enables more detailed CPU scopes to be emitted for the “cpu” trace channel.
- The “AssetLoadTime” trace channel is now only used for commandlets (ex. cooking) to enable tracing of object names (blueprints, functions) as cpu scopes. In this case, it also requires “cpu” channel (and “-statnamedevents”) to be enabled. The CPU scope tracing of object names (blueprints, functions) is now enabled by default when app is not running as a commandlet (still requires “cpu” trace channel and “-statnamedevents” to be enabled, but it does not require “AssetLoadTime” channel to be enabled).
- The “LoadTime” channel will enable the Asset Loading Insights functionality (custom tracks for the async loading events and more performance data regarding asset loading available as tables).
Regards,
Ionut