Add more memory profiler categories

This commit is contained in:
Wojtek Figat
2025-05-25 18:38:07 +02:00
parent a74c5e7943
commit 9dc4dbc6d7
6 changed files with 112 additions and 38 deletions

View File

@@ -18,6 +18,7 @@
#include "Engine/Serialization/Serialization.h"
#include "Engine/Serialization/JsonWriter.h"
#include "Engine/Profiler/ProfilerCPU.h"
#include "Engine/Profiler/ProfilerMemory.h"
#include "Engine/Utilities/StringConverter.h"
#include "Engine/Threading/MainThreadTask.h"
#include "Engine/Level/SceneObject.h"
@@ -1340,6 +1341,8 @@ bool VisualScript::Save(const StringView& path)
Asset::LoadResult VisualScript::load()
{
PROFILE_MEM(ScriptingVisual);
// Build Visual Script typename that is based on asset id
String typeName = _id.ToString();
StringUtils::ConvertUTF162ANSI(typeName.Get(), _typenameChars, 32);
@@ -1532,6 +1535,7 @@ Asset::LoadResult VisualScript::load()
void VisualScript::unload(bool isReloading)
{
PROFILE_MEM(ScriptingVisual);
#if USE_EDITOR
if (isReloading)
{
@@ -1588,6 +1592,7 @@ AssetChunksFlag VisualScript::getChunksToPreload() const
void VisualScript::CacheScriptingType()
{
PROFILE_MEM(ScriptingVisual);
ScopeLock lock(VisualScriptingBinaryModule::Locker);
auto& binaryModule = VisualScriptingModule;
@@ -1723,6 +1728,7 @@ ScriptingObject* VisualScriptingBinaryModule::VisualScriptObjectSpawn(const Scri
VisualScript* visualScript = VisualScriptingModule.Scripts[params.Type.TypeIndex];
// Initialize instance data
PROFILE_MEM(ScriptingVisual);
ScopeLock lock(visualScript->Locker);
auto& instanceParams = visualScript->_instances[object->GetID()].Params;
instanceParams.Resize(visualScript->Graph.Parameters.Count());
@@ -1747,6 +1753,8 @@ ScriptingObject* VisualScriptingBinaryModule::VisualScriptObjectSpawn(const Scri
void VisualScriptingBinaryModule::OnScriptsReloading()
{
PROFILE_MEM(ScriptingVisual);
// Clear any cached types from that module across all loaded Visual Scripts
for (auto& script : Scripts)
{
@@ -1795,6 +1803,7 @@ void VisualScriptingBinaryModule::OnScriptsReloading()
void VisualScriptingBinaryModule::OnEvent(ScriptingObject* object, Span<Variant> parameters, ScriptingTypeHandle eventType, StringView eventName)
{
PROFILE_MEM(ScriptingVisual);
if (object)
{
// Object event
@@ -1956,6 +1965,7 @@ bool VisualScriptingBinaryModule::GetFieldValue(void* field, const Variant& inst
bool VisualScriptingBinaryModule::SetFieldValue(void* field, const Variant& instance, Variant& value)
{
PROFILE_MEM(ScriptingVisual);
const auto vsFiled = (VisualScript::Field*)field;
const auto instanceObject = (ScriptingObject*)instance;
if (!instanceObject)
@@ -2042,6 +2052,7 @@ void VisualScriptingBinaryModule::SerializeObject(JsonWriter& stream, ScriptingO
void VisualScriptingBinaryModule::DeserializeObject(ISerializable::DeserializeStream& stream, ScriptingObject* object, ISerializeModifier* modifier)
{
PROFILE_MEM(ScriptingVisual);
ASSERT(stream.IsObject());
Locker.Lock();
const auto asset = Scripts[object->GetTypeHandle().TypeIndex].Get();
@@ -2165,6 +2176,7 @@ const Variant& VisualScript::GetScriptInstanceParameterValue(const StringView& n
void VisualScript::SetScriptInstanceParameterValue(const StringView& name, ScriptingObject* instance, const Variant& value)
{
PROFILE_MEM(ScriptingVisual);
CHECK(instance);
for (int32 paramIndex = 0; paramIndex < Graph.Parameters.Count(); paramIndex++)
{
@@ -2186,6 +2198,7 @@ void VisualScript::SetScriptInstanceParameterValue(const StringView& name, Scrip
void VisualScript::SetScriptInstanceParameterValue(const StringView& name, ScriptingObject* instance, Variant&& value)
{
PROFILE_MEM(ScriptingVisual);
CHECK(instance);
for (int32 paramIndex = 0; paramIndex < Graph.Parameters.Count(); paramIndex++)
{
@@ -2383,6 +2396,7 @@ VisualScriptingBinaryModule* VisualScripting::GetBinaryModule()
Variant VisualScripting::Invoke(VisualScript::Method* method, ScriptingObject* instance, Span<Variant> parameters)
{
PROFILE_MEM(ScriptingVisual);
CHECK_RETURN(method && method->Script->IsLoaded(), Variant::Zero);
PROFILE_CPU_SRC_LOC(method->ProfilerData);
@@ -2423,6 +2437,7 @@ bool VisualScripting::Evaluate(VisualScript* script, ScriptingObject* instance,
const auto box = node->GetBox(boxId);
if (!box)
return false;
PROFILE_MEM(ScriptingVisual);
// Add to the calling stack
ScopeContext scope;

View File

@@ -2,6 +2,7 @@
#include "ArenaAllocation.h"
#include "../Math/Math.h"
#include "Engine/Profiler/ProfilerMemory.h"
void ArenaAllocator::Free()
{
@@ -9,6 +10,9 @@ void ArenaAllocator::Free()
Page* page = _first;
while (page)
{
#if COMPILE_WITH_PROFILER
ProfilerMemory::OnGroupUpdate(ProfilerMemory::Groups::MallocArena, -page->Size, -1);
#endif
Allocator::Free(page->Memory);
Page* next = page->Next;
Allocator::Free(page);
@@ -30,6 +34,9 @@ void* ArenaAllocator::Allocate(uint64 size, uint64 alignment)
if (!page)
{
uint64 pageSize = Math::Max<uint64>(_pageSize, size);
#if COMPILE_WITH_PROFILER
ProfilerMemory::OnGroupUpdate(ProfilerMemory::Groups::MallocArena, pageSize, 1);
#endif
page = (Page*)Allocator::Allocate(sizeof(Page));
page->Memory = Allocator::Allocate(pageSize);
page->Next = _first;

View File

@@ -244,7 +244,15 @@ bool GPUBuffer::Init(const GPUBufferDescription& desc)
LOG(Warning, "Cannot initialize buffer. Description: {0}", desc.ToString());
return true;
}
PROFILE_MEM_INC(GraphicsBuffers, GetMemoryUsage());
#if COMPILE_WITH_PROFILER
auto group = ProfilerMemory::Groups::GraphicsBuffers;
if (EnumHasAnyFlags(_desc.Flags, GPUBufferFlags::VertexBuffer))
group = ProfilerMemory::Groups::GraphicsVertexBuffers;
else if (EnumHasAnyFlags(_desc.Flags, GPUBufferFlags::IndexBuffer))
group = ProfilerMemory::Groups::GraphicsIndexBuffers;
ProfilerMemory::IncrementGroup(group, _memoryUsage);
#endif
return false;
}
@@ -480,7 +488,15 @@ GPUResourceType GPUBuffer::GetResourceType() const
void GPUBuffer::OnReleaseGPU()
{
PROFILE_MEM_DEC(GraphicsBuffers, GetMemoryUsage());
#if COMPILE_WITH_PROFILER
auto group = ProfilerMemory::Groups::GraphicsBuffers;
if (EnumHasAnyFlags(_desc.Flags, GPUBufferFlags::VertexBuffer))
group = ProfilerMemory::Groups::GraphicsVertexBuffers;
else if (EnumHasAnyFlags(_desc.Flags, GPUBufferFlags::IndexBuffer))
group = ProfilerMemory::Groups::GraphicsIndexBuffers;
ProfilerMemory::IncrementGroup(group, _memoryUsage);
#endif
_desc.Clear();
_isLocked = false;
}

View File

@@ -503,7 +503,17 @@ bool GPUTexture::Init(const GPUTextureDescription& desc)
LOG(Warning, "Cannot initialize texture. Description: {0}", desc.ToString());
return true;
}
PROFILE_MEM_INC(GraphicsTextures, GetMemoryUsage());
#if COMPILE_WITH_PROFILER
auto group = ProfilerMemory::Groups::GraphicsTextures;
if (_desc.IsRenderTarget())
group = ProfilerMemory::Groups::GraphicsRenderTargets;
else if (_desc.IsCubeMap())
group = ProfilerMemory::Groups::GraphicsCubeMaps;
else if (_desc.IsVolume())
group = ProfilerMemory::Groups::GraphicsVolumeTextures;
ProfilerMemory::IncrementGroup(group, _memoryUsage);
#endif
// Render targets and depth buffers doesn't support normal textures streaming and are considered to be always resident
if (IsRegularTexture() == false)
@@ -593,7 +603,17 @@ GPUResourceType GPUTexture::GetResourceType() const
void GPUTexture::OnReleaseGPU()
{
PROFILE_MEM_DEC(GraphicsTextures, GetMemoryUsage());
#if COMPILE_WITH_PROFILER
auto group = ProfilerMemory::Groups::GraphicsTextures;
if (_desc.IsRenderTarget())
group = ProfilerMemory::Groups::GraphicsRenderTargets;
else if (_desc.IsCubeMap())
group = ProfilerMemory::Groups::GraphicsCubeMaps;
else if (_desc.IsVolume())
group = ProfilerMemory::Groups::GraphicsVolumeTextures;
ProfilerMemory::DecrementGroup(group, _memoryUsage);
#endif
_desc.Clear();
_residentMipLevels = 0;
}

View File

@@ -25,14 +25,14 @@ struct GroupNameBuffer
Char Buffer[30];
template<typename T>
void Set(const T* str)
void Set(const T* str, bool autoFormat = false)
{
int32 max = StringUtils::Length(str), dst = 0;
char prev = 0;
for (int32 i = 0; i < max && dst < ARRAY_COUNT(Buffer) - 2; i++)
{
char cur = str[i];
if (StringUtils::IsUpper(cur) && StringUtils::IsLower(prev))
if (autoFormat && StringUtils::IsUpper(cur) && StringUtils::IsLower(prev))
Buffer[dst++] = '/';
Buffer[dst++] = cur;
prev = cur;
@@ -52,10 +52,6 @@ struct GroupStackData
{
if (Count < ARRAY_COUNT(Stack))
Count++;
else
{
int a= 10;
}
Stack[Count - 1] = (uint8)group;
}
@@ -112,8 +108,15 @@ namespace
for (int32 i = 0; i < GROUPS_COUNT; i++)
{
const char* name = ScriptingEnum::GetName((ProfilerMemory::Groups)i);
GroupNames[i].Set(name);
GroupNames[i].Set(name, true);
}
#define RENAME_GROUP(group, name) GroupNames[(int32)ProfilerMemory::Groups::group].Set(name)
RENAME_GROUP(GraphicsRenderTargets, "Graphics/RenderTargets");
RENAME_GROUP(GraphicsCubeMaps, "Graphics/CubeMaps");
RENAME_GROUP(GraphicsVolumeTextures, "Graphics/VolumeTextures");
RENAME_GROUP(GraphicsVertexBuffers, "Graphics/VertexBuffers");
RENAME_GROUP(GraphicsIndexBuffers, "Graphics/IndexBuffers");
#undef RENAME_GROUP
// Init constant memory
PROFILE_MEM_INC(ProgramSize, Platform::GetMemoryStats().ProgramSizeMemory);
@@ -162,31 +165,6 @@ namespace
output.AppendLine();
}
#if 0
// Print count of memory allocs count per group
for (int32 i = 0; i < GROUPS_COUNT; i++)
{
GroupInfo& group = groups[i];
group.Group = (ProfilerMemory::Groups)i;
group.Size = 0;
}
PointersLocker.Lock();
for (auto& e : Pointers)
groups[e.Value.Group].Size++;
PointersLocker.Unlock();
Sorting::QuickSort(groups, GROUPS_COUNT);
output.Append(TEXT("Memory allocations count summary:")).AppendLine();
for (int32 i = 0; i < maxCount; i++)
{
const GroupInfo& group = groups[i];
if (group.Size == 0)
break;
const Char* name = GroupName[(int32)group.Group].Buffer;
output.AppendFormat(TEXT("{:>30}: {:>11}"), name, group.Size);
output.AppendLine();
}
#endif
// Warn that data might be missing due to inactive profiler
if (!ProfilerMemory::Enabled)
output.AppendLine(TEXT("Detailed memory profiling is disabled. Run with command line: -mem"));
@@ -243,8 +221,14 @@ void InitProfilerMemory(const Char* cmdLine)
// Init hierarchy
#define INIT_PARENT(parent, child) GroupParents[(int32)ProfilerMemory::Groups::child] = (uint8)ProfilerMemory::Groups::parent
INIT_PARENT(Malloc, MallocArena);
INIT_PARENT(Graphics, GraphicsTextures);
INIT_PARENT(Graphics, GraphicsRenderTargets);
INIT_PARENT(Graphics, GraphicsCubeMaps);
INIT_PARENT(Graphics, GraphicsVolumeTextures);
INIT_PARENT(Graphics, GraphicsBuffers);
INIT_PARENT(Graphics, GraphicsVertexBuffers);
INIT_PARENT(Graphics, GraphicsIndexBuffers);
INIT_PARENT(Graphics, GraphicsMeshes);
INIT_PARENT(Graphics, GraphicsShaders);
INIT_PARENT(Graphics, GraphicsMaterials);
@@ -414,4 +398,11 @@ void ProfilerMemory::OnMemoryFree(void* ptr)
stack.SkipRecursion = false;
}
void ProfilerMemory::OnGroupUpdate(Groups group, int64 sizeDelta, int64 countDetla)
{
Platform::InterlockedAdd(&GroupMemory[(int32)group], sizeDelta);
Platform::InterlockedAdd(&GroupMemoryCount[(int32)group], countDetla);
UPDATE_PEEK(group);
}
#endif

View File

@@ -30,19 +30,32 @@ public:
TotalUntracked,
// Initial memory used by program upon startup (eg. executable size, static variables).
ProgramSize,
// Total memory allocated via malloc.
Malloc,
// General purpose engine memory.
Engine,
// Profiling tool memory overhead.
Profiler,
// Total memory allocated via dynamic memory allocations.
Malloc,
// Total memory allocated via arena allocators (all pages).
MallocArena,
// Total graphics memory usage.
Graphics,
// Total textures memory usage.
GraphicsTextures,
// Total render targets memory usage (textures used as target image for rendering).
GraphicsRenderTargets,
// Total cubemap textures memory usage (each cubemap is 6 textures).
GraphicsCubeMaps,
// Total volume textures memory usage (3D textures).
GraphicsVolumeTextures,
// Total buffers memory usage.
GraphicsBuffers,
// Total vertex buffers memory usage.
GraphicsVertexBuffers,
// Total index buffers memory usage.
GraphicsIndexBuffers,
// Total meshes memory usage (vertex and idnex buffers allocated by models).
GraphicsMeshes,
// Totoal shaders memory usage (shaders bytecode, PSOs data).
@@ -95,6 +108,8 @@ public:
// Total scripting memory allocated by game.
Scripting,
// Total Visual scripting memory allocated by game (visual script graphs, data and runtime allocations).
ScriptingVisual,
// Total User Interface components memory.
UI,
@@ -144,6 +159,15 @@ public:
// Custom plugin-specific memory tracking.
CustomPlugin9,
// Custom platform-specific memory tracking.
CustomPlatform0,
// Custom platform-specific memory tracking.
CustomPlatform1,
// Custom platform-specific memory tracking.
CustomPlatform2,
// Custom platform-specific memory tracking.
CustomPlatform3,
// Total editor-specific memory.
Editor,
@@ -219,6 +243,7 @@ public:
static void OnMemoryAlloc(void* ptr, uint64 size);
static void OnMemoryFree(void* ptr);
static void OnGroupUpdate(Groups group, int64 sizeDelta, int64 countDetla);
public:
/// <summary>