Choose your operating system:
Windows
macOS
Linux
低级内存跟踪器(Low-Level Memory Tracker)(简称 LLM)是一种跟踪虚幻引擎项目中内存使用情况的工具。LLM使用范围标记系统来记录虚幻引擎和操作系统分配的所有内存。
LLM跟踪器
LLM目前有两个跟踪器。每个跟踪器都有自己的分配映射和标记堆栈。默认跟踪器适用于引擎的所有分配。在这两个跟踪器中,它的级别较高并记录通过 FMemory
类函数 Malloc
进行的分配。该跟踪器可为 stat LLM
和 stat LLMFULL
控制台命令提供统计信息。平台跟踪器是较低级别的版本,它记录从OS进行的所有分配。例如,它会跟踪 Binned2
等函数进行的内部分配。因此,默认跟踪器统计信息是平台跟踪器统计信息的子集。
LLM设置
要在项目中启用LLM,请使用以下命令行参数和控制台命令。
命令行参数 |
说明 |
---|---|
|
启用LLM |
|
连续将所有值写入CSV文件。自动启用-LLM。 |
|
实验性功能。显示每个资源分配的内存总计。 |
|
实验性功能。显示每个UObject类类型的总计。 |
控制台命令 |
说明 |
---|---|
|
显示LLM摘要。所有较低级别的引擎统计信息都归入单个引擎统计信息。 |
|
显示所有LLM统计信息。 |
|
显示从OS分配的所有内存的统计信息。 |
|
显示LLM内部使用的内存。 |
使用 -LLMCSV
命令行参数时,.CSV
文件将写入 saved/profiling/llm/
。该文件将包含每个标记的列,以MB为单位显示当前值。每隔5秒写一个新行(默认情况下)。此频率可以使用 LLM.LLMWriteInterval
控制台变量更改。
LLM标记
引擎(包括游戏代码)的每次内存分配都会被指定一个标记值,用于标识其所属的类别。也就是说,所有内存仅被跟踪一次,没有任何内存错过或被计算两次。所有类别的总计会累计到游戏所用的总内存。
这些标记使用标记范围宏进行应用。在该范围内应用的任何分配都会被分配指定标记。LLM维护有一个标记范围堆栈,并将顶部标记应用于分配。LLM统计信息可以在游戏中使用 stat LLM
或 stat LLMFULL
控制台命令进行查看。每个标记的当前总计将以MB为单位显示。LLM还会将统计信息值写入 .CSV
文件,以便分析这些值。引擎中当前存在以下标记类别:
标记名称 |
说明 |
---|---|
UObject |
该标记包括从 |
EngineMisc |
任何其他类别中未跟踪的所有低级内存。 |
TaskGraphTasksMisc |
从任务图中启动的任何没有自己类别的任务。该任务通常级别应较低。 |
StaticMesh |
该标记是 |
要添加新的标记,需要执行以下步骤:
将值添加到
LowLevelMemTracker.h
中的ELLMTag
列举类型。将相应的元素添加到
LowLevelMemTracker.cpp
中的ELLMTagNames
数组中。使用
LLM_SCOPE
宏将标记范围添加到代码中。
如果范围是特定于平台的,则以相同的方式添加到特定于平台的LLM文件中的列举类型,例如,PlayStation 4的 PS4LLM.cpp
和 PS4LLM.h
。
标记集(实验性)
要使用标记集,请在 LowLevelMemory.h
中定义 LLM_ALLOW_ASSETS_TAGS
。使用标记集时,每个分配还将存储资源名称或Object类名称。
使用标记集将增加内存占用和运行时性能耗用。
技术实现细节
LLM的作用原理是维护由指针索引的所有分配的映射。该映射当前包含每个分配的大小及其指定的标记。游戏一次可有多达400万个实时分配,因此内存开销必须尽可能少。当前实现中每个分配使用21个字节:
分配 |
大小 |
---|---|
指针 |
8个字节 |
指针散列键 |
4个字节 |
大小 |
4个字节 |
标记 |
1个字节 |
散列图索引 |
4个字节 |
使用 OnLowLevelAlloc
函数跟踪分配时,标记堆栈顶部的标记将成为当前标记,并存储在分配映射中,以该指针作为其关键帧。为了避免争用,在单独的 FLLMThreadState
类实例中跟踪每个标记的帧增量。在帧结束时,这些增量将相加并发布到统计信息系统和 .CSV
文件。
LLM早已被初始化,也就是说它必须默认启用。如果未在命令行上启用LLM,它将自行关闭并清理所有内存,以确保没有占用内存。LLM完全在"测试"和"发行"构建中编译。
LLM可在没有统计信息系统的情况下运行(例如在"测试"配置中)。如果这样,屏幕上将无法显示统计信息,但统计信息仍将写入 .CSV
文件。LLM将需要通过修改 LowLevelMemTracker.h
中的 ENABLE_LOW_LEVEL_MEM_TRACKER
来启用。
标记使用范围宏进行应用。以下是两个主要的宏:
LLM_SCOPE(Tag)
LLM_PLATFORM_SCOPE(Tag)
这两个宏分别设置了默认跟踪器和平台跟踪器的当前范围。这些范围有平台相关版本,例如 LLM_SCOPE_PS4(Tag)
,它使用特定于平台的标记列举类型。使用统计信息的范围宏(例如 LLM_SCOPED_TAG_WITH_STAT
)目前被视为已弃用,不应被使用。
LLM内部使用的所有内存均由平台提供的 LLMAlloc
和 LLMFree
函数管理。LLM不以任何其他方式进行分配,因此它不会跟踪自己的内存使用情况(并导致无穷递归),这一点非常重要。
其他技术细节
以下部分介绍了使用LLM时应注意的各种注释和其他信息。
因为LLM占用的内存可能高达100MB甚至更多,所以强烈建议在控制台上以大内存模式运行:
如果使用PlayStation 4,请转至控制台的"目标设置(Target Settings)",然后将"内存预算模式(Memory Budget Mode)"更改为"LARGE"。
如果使用XBox One,请转至XBox One Manager的"设置(Settings)"选项卡,将"调试内存模式(Debug Memory Mode)"设置为"Pix and Title"。
测试配置中的LLM不会显示屏幕统计信息页面,但会写出
.CSV
文件。在发售时LLM完全禁用。在PlayStation 4上,LLM需要预留供内部使用的内存(目前为600MB)。如果PlayStation 4移动到新的内存系统(
PS4Memory2.cpp
),将无需再满足这一要求。资源标记跟踪仍处于早期实验状态。