Add more memory profiling coverage

This commit is contained in:
Wojtek Figat
2025-06-06 14:38:22 +02:00
parent 9d8e75caa3
commit cd637e8a7a
14 changed files with 57 additions and 3 deletions

View File

@@ -1425,6 +1425,7 @@ bool FlaxStorage::CloseFileHandles()
return false;
}
PROFILE_CPU();
PROFILE_MEM(ContentFiles);
// Note: this is usually called by the content manager when this file is not used or on exit
// In those situations all the async tasks using this storage should be cancelled externally

View File

@@ -12,6 +12,9 @@
#include "Engine/Threading/Threading.h"
#include "Engine/Core/Collections/HashSet.h"
#endif
#if COMPILE_WITH_PROFILER
#include "Engine/Profiler/ProfilerMemory.h"
#endif
/// <summary>
/// The function object that supports binding static, member and lambda functions.
@@ -457,6 +460,7 @@ public:
/// <param name="f">The function to bind.</param>
void Bind(const FunctionType& f)
{
PROFILE_MEM(EngineDelegate);
#if DELEGATE_USE_ATOMIC
const intptr size = Platform::AtomicRead(&_size);
FunctionType* bindings = (FunctionType*)Platform::AtomicRead(&_ptr);

View File

@@ -628,6 +628,7 @@ GPUTask* GPUTexture::UploadMipMapAsync(const BytesContainer& data, int32 mipInde
GPUTask* GPUTexture::UploadMipMapAsync(const BytesContainer& data, int32 mipIndex, int32 rowPitch, int32 slicePitch, bool copyData)
{
PROFILE_CPU();
PROFILE_MEM(GraphicsTextures);
ASSERT(IsAllocated());
ASSERT(mipIndex < MipLevels() && data.IsValid());
ASSERT(data.Length() >= slicePitch);
@@ -720,6 +721,7 @@ bool GPUTexture::DownloadData(TextureData& result)
MISSING_CODE("support volume texture data downloading.");
}
PROFILE_CPU();
PROFILE_MEM(GraphicsTextures);
// Use faster path for staging resources
if (IsStaging()) // TODO: what about chips with unified memory? if rendering is not active then we can access GPU memory from CPU directly (eg. mobile, integrated GPUs and some consoles)
@@ -806,6 +808,7 @@ Task* GPUTexture::DownloadDataAsync(TextureData& result)
MISSING_CODE("support volume texture data downloading.");
}
PROFILE_CPU();
PROFILE_MEM(GraphicsTextures);
// Use faster path for staging resources
if (IsStaging())

View File

@@ -169,6 +169,7 @@ void Mouse::OnMouseMoved(const Float2& newPosition)
void Mouse::OnMouseDown(const Float2& position, const MouseButton button, Window* target)
{
PROFILE_MEM(Input);
Event& e = _queue.AddOne();
e.Type = EventType::MouseDown;
e.Target = target;
@@ -187,6 +188,7 @@ bool Mouse::IsAnyButtonDown() const
void Mouse::OnMouseUp(const Float2& position, const MouseButton button, Window* target)
{
PROFILE_MEM(Input);
Event& e = _queue.AddOne();
e.Type = EventType::MouseUp;
e.Target = target;
@@ -196,6 +198,7 @@ void Mouse::OnMouseUp(const Float2& position, const MouseButton button, Window*
void Mouse::OnMouseDoubleClick(const Float2& position, const MouseButton button, Window* target)
{
PROFILE_MEM(Input);
Event& e = _queue.AddOne();
e.Type = EventType::MouseDoubleClick;
e.Target = target;
@@ -205,6 +208,7 @@ void Mouse::OnMouseDoubleClick(const Float2& position, const MouseButton button,
void Mouse::OnMouseMove(const Float2& position, Window* target)
{
PROFILE_MEM(Input);
Event& e = _queue.AddOne();
e.Type = EventType::MouseMove;
e.Target = target;
@@ -213,6 +217,7 @@ void Mouse::OnMouseMove(const Float2& position, Window* target)
void Mouse::OnMouseLeave(Window* target)
{
PROFILE_MEM(Input);
Event& e = _queue.AddOne();
e.Type = EventType::MouseLeave;
e.Target = target;
@@ -220,6 +225,7 @@ void Mouse::OnMouseLeave(Window* target)
void Mouse::OnMouseWheel(const Float2& position, float delta, Window* target)
{
PROFILE_MEM(Input);
Event& e = _queue.AddOne();
e.Type = EventType::MouseWheel;
e.Target = target;
@@ -316,6 +322,7 @@ void Keyboard::OnCharInput(Char c, Window* target)
if (c < 32)
return;
PROFILE_MEM(Input);
Event& e = _queue.AddOne();
e.Type = EventType::Char;
e.Target = target;
@@ -326,6 +333,7 @@ void Keyboard::OnKeyUp(KeyboardKeys key, Window* target)
{
if (key >= KeyboardKeys::MAX)
return;
PROFILE_MEM(Input);
Event& e = _queue.AddOne();
e.Type = EventType::KeyUp;
e.Target = target;
@@ -336,6 +344,7 @@ void Keyboard::OnKeyDown(KeyboardKeys key, Window* target)
{
if (key >= KeyboardKeys::MAX)
return;
PROFILE_MEM(Input);
Event& e = _queue.AddOne();
e.Type = EventType::KeyDown;
e.Target = target;

View File

@@ -3,6 +3,7 @@
#if COMPILE_WITH_PROFILER
#include "ProfilerCPU.h"
#include "ProfilerMemory.h"
#include "Engine/Engine/Globals.h"
#include "Engine/Threading/ThreadRegistry.h"
@@ -157,6 +158,7 @@ int32 ProfilerCPU::BeginEvent()
auto thread = Thread::Current;
if (thread == nullptr)
{
PROFILE_MEM(Profiler);
const auto id = Platform::GetCurrentThreadID();
const auto t = ThreadRegistry::GetThread(id);
if (t)

View File

@@ -3,6 +3,7 @@
#if COMPILE_WITH_PROFILER
#include "ProfilerGPU.h"
#include "ProfilerMemory.h"
#include "Engine/Core/Log.h"
#include "Engine/Engine/Engine.h"
#include "Engine/Graphics/GPUDevice.h"
@@ -45,6 +46,7 @@ void ProfilerGPU::EventBuffer::TryResolve()
}
// Collect queries results and free them
PROFILE_MEM(Profiler);
for (int32 i = 0; i < _data.Count(); i++)
{
auto& e = _data[i];
@@ -58,6 +60,7 @@ void ProfilerGPU::EventBuffer::TryResolve()
int32 ProfilerGPU::EventBuffer::Add(const Event& e)
{
PROFILE_MEM(Profiler);
const int32 index = _data.Count();
_data.Add(e);
return index;
@@ -88,6 +91,7 @@ GPUTimerQuery* ProfilerGPU::GetTimerQuery()
}
else
{
PROFILE_MEM(Profiler);
result = GPUDevice::Instance->CreateTimerQuery();
_timerQueriesPool.Add(result);
}

View File

@@ -234,6 +234,8 @@ void InitProfilerMemory(const Char* cmdLine, int32 stage)
// Init hierarchy
#define INIT_PARENT(parent, child) GroupParents[(int32)ProfilerMemory::Groups::child] = (uint8)ProfilerMemory::Groups::parent
INIT_PARENT(Engine, EngineThreading);
INIT_PARENT(Engine, EngineDelegate);
INIT_PARENT(Malloc, MallocArena);
INIT_PARENT(Graphics, GraphicsTextures);
INIT_PARENT(Graphics, GraphicsRenderTargets);

View File

@@ -30,8 +30,6 @@ public:
TotalUntracked,
// Initial memory used by program upon startup (eg. executable size, static variables).
ProgramSize,
// General purpose engine memory.
Engine,
// Profiling tool memory overhead.
Profiler,
@@ -40,6 +38,13 @@ public:
// Total memory allocated via arena allocators (all pages).
MallocArena,
// General purpose engine memory.
Engine,
// Memory used by the threads (and relevant systems such as Job System).
EngineThreading,
// Memory used by Delegate (engine events system to store all references).
EngineDelegate,
// Total graphics memory usage.
Graphics,
// Total textures memory usage.

View File

@@ -3,6 +3,7 @@
#pragma once
#include "Engine/Core/Memory/Memory.h"
#include "Engine/Profiler/ProfilerMemory.h"
#define MOODYCAMEL_EXCEPTIONS_ENABLED 0
#include <ThirdParty/concurrentqueue.h>
@@ -17,6 +18,7 @@ struct ConcurrentQueueSettings : public moodycamel::ConcurrentQueueDefaultTraits
// Use default engine memory allocator
static inline void* malloc(size_t size)
{
PROFILE_MEM(EngineThreading);
return Allocator::Allocate((uint64)size);
}

View File

@@ -12,6 +12,7 @@
#include "Engine/Core/Collections/RingBuffer.h"
#include "Engine/Engine/EngineService.h"
#include "Engine/Profiler/ProfilerCPU.h"
#include "Engine/Profiler/ProfilerMemory.h"
#if USE_CSHARP
#include "Engine/Scripting/ManagedCLR/MCore.h"
#endif
@@ -118,17 +119,22 @@ void* JobSystemAllocation::Allocate(uintptr size)
}
}
if (!result)
{
PROFILE_MEM(EngineThreading);
result = Platform::Allocate(size, 16);
}
return result;
}
void JobSystemAllocation::Free(void* ptr, uintptr size)
{
PROFILE_MEM(EngineThreading);
MemPool.Add({ ptr, size });
}
bool JobSystemService::Init()
{
PROFILE_MEM(EngineThreading);
ThreadsCount = Math::Min<int32>(Platform::GetCPUInfo().LogicalProcessorCount, ARRAY_COUNT(Threads));
for (int32 i = 0; i < ThreadsCount; i++)
{

View File

@@ -14,6 +14,7 @@
#include "Engine/Platform/ConditionVariable.h"
#include "Engine/Platform/CPUInfo.h"
#include "Engine/Platform/Thread.h"
#include "Engine/Profiler/ProfilerMemory.h"
FLAXENGINE_API bool IsInMainThread()
{
@@ -36,6 +37,7 @@ String ThreadPoolTask::ToString() const
void ThreadPoolTask::Enqueue()
{
PROFILE_MEM(EngineThreading);
ThreadPoolImpl::Jobs.Add(this);
ThreadPoolImpl::JobsSignal.NotifyOne();
}
@@ -58,6 +60,8 @@ ThreadPoolService ThreadPoolServiceInstance;
bool ThreadPoolService::Init()
{
PROFILE_MEM(EngineThreading);
// Spawn threads
const int32 numThreads = Math::Clamp<int32>(Platform::GetCPUInfo().ProcessorCoreCount - 1, 2, PLATFORM_THREADS_LIMIT / 2);
LOG(Info, "Spawning {0} Thread Pool workers", numThreads);

View File

@@ -3,10 +3,11 @@
#include "ThreadRegistry.h"
#include "Engine/Core/Collections/Dictionary.h"
#include "Engine/Platform/CriticalSection.h"
#include "Engine/Profiler/ProfilerMemory.h"
namespace ThreadRegistryImpl
{
Dictionary<uint64, Thread*> Registry(64);
Dictionary<uint64, Thread*> Registry;
CriticalSection Locker;
}
@@ -46,6 +47,7 @@ void ThreadRegistry::KillEmAll()
void ThreadRegistry::Add(Thread* thread)
{
PROFILE_MEM(EngineThreading);
ASSERT(thread && thread->GetID() != 0);
Locker.Lock();
ASSERT(!Registry.ContainsKey(thread->GetID()) && !Registry.ContainsValue(thread));

View File

@@ -14,6 +14,7 @@
#include "Engine/Graphics/PixelFormatSampler.h"
#include "Engine/Graphics/Textures/TextureData.h"
#include "Engine/Profiler/ProfilerCPU.h"
#include "Engine/Profiler/ProfilerMemory.h"
#if USE_EDITOR
#include "Engine/Core/Collections/Dictionary.h"
@@ -210,6 +211,7 @@ bool TextureTool::HasAlpha(const StringView& path)
bool TextureTool::ImportTexture(const StringView& path, TextureData& textureData)
{
PROFILE_CPU();
PROFILE_MEM(GraphicsTextures);
LOG(Info, "Importing texture from \'{0}\'", path);
const auto startTime = DateTime::NowUTC();
@@ -247,6 +249,7 @@ bool TextureTool::ImportTexture(const StringView& path, TextureData& textureData
bool TextureTool::ImportTexture(const StringView& path, TextureData& textureData, Options options, String& errorMsg)
{
PROFILE_CPU();
PROFILE_MEM(GraphicsTextures);
LOG(Info, "Importing texture from \'{0}\'. Options: {1}", path, options.ToString());
const auto startTime = DateTime::NowUTC();
@@ -296,6 +299,7 @@ bool TextureTool::ImportTexture(const StringView& path, TextureData& textureData
bool TextureTool::ExportTexture(const StringView& path, const TextureData& textureData)
{
PROFILE_CPU();
PROFILE_MEM(GraphicsTextures);
LOG(Info, "Exporting texture to \'{0}\'.", path);
const auto startTime = DateTime::NowUTC();
ImageType type;
@@ -346,6 +350,7 @@ bool TextureTool::Convert(TextureData& dst, const TextureData& src, const PixelF
return true;
}
PROFILE_CPU();
PROFILE_MEM(GraphicsTextures);
#if COMPILE_WITH_DIRECTXTEX
return ConvertDirectXTex(dst, src, dstFormat);
@@ -375,6 +380,7 @@ bool TextureTool::Resize(TextureData& dst, const TextureData& src, int32 dstWidt
return true;
}
PROFILE_CPU();
PROFILE_MEM(GraphicsTextures);
#if COMPILE_WITH_DIRECTXTEX
return ResizeDirectXTex(dst, src, dstWidth, dstHeight);
#elif COMPILE_WITH_STB
@@ -488,6 +494,7 @@ bool TextureTool::GetImageType(const StringView& path, ImageType& type)
bool TextureTool::Transform(TextureData& texture, const Function<void(Color&)>& transformation)
{
PROFILE_CPU();
PROFILE_MEM(GraphicsTextures);
auto sampler = PixelFormatSampler::Get(texture.Format);
if (!sampler)
return true;

View File

@@ -82,6 +82,7 @@ bool CaptureScreenshot::Run()
LOG(Warning, "Missing target render task.");
return true;
}
PROFILE_MEM(Graphics);
// TODO: how about a case two or more screenshots at the same second? update counter and check files
@@ -147,6 +148,7 @@ void Screenshot::Capture(GPUTexture* target, const StringView& path)
LOG(Warning, "Cannot take screenshot. Graphics device is not ready.");
return;
}
PROFILE_MEM(Graphics);
// Faster path for staging textures that contents are ready to access on a CPU
if (target->IsStaging())
@@ -211,6 +213,7 @@ void Screenshot::Capture(SceneRenderTask* target, const StringView& path)
LOG(Warning, "Cannot take screenshot. Graphics device is not ready.");
return;
}
PROFILE_MEM(Graphics);
// Create tasks
auto saveTask = New<CaptureScreenshot>(target, path);