#pragma once #include "BeefySysLib/Common.h" #include "BeefySysLib/util/CritSect.h" #include "BeefySysLib/util/Hash.h" #include "BeefySysLib/util/String.h" #include "BeefySysLib/util/BumpAllocator.h" #include "BeefySysLib/util/Dictionary.h" #include NS_BF_BEGIN class MemReporter { public: struct Entry { Dictionary mChildren; String mName; int mSize; int mChildSize; int mCount; Entry* mParent; Entry() { mSize = 0; mChildSize = -1; mParent = NULL; mCount = 0; } }; BumpAllocator mAlloc; Entry mRoot; Entry* mCurEntry; bool mShowInKB; public: int GetChildSizes(Entry* entry); void Report(int depth, Entry* entry); public: MemReporter(); ~MemReporter(); void BeginSection(const StringView& name); void Add(int size); void Add(const StringView& name, int size); template void AddVec(const T& vec, bool addContainerSize = true) { Add((addContainerSize ? sizeof(T) : 0) + (int)vec.mAllocSize * sizeof(typename T::value_type)); } template void AddVec(const StringView& name, const T& vec, bool addContainerSize = true) { BeginSection(name); Add((addContainerSize ? sizeof(T) : 0) + (int)vec.mAllocSize * sizeof(typename T::value_type)); EndSection(); } template void AddVecPtr(const std::vector& vec, bool addContainerSize = true) { Add((addContainerSize ? sizeof(T) : 0) + (int)vec.capacity() * sizeof(T) + (int)vec.size() * sizeof(typename std::remove_pointer::type)); //-V220 } template void AddVecPtr(const Array& vec, bool addContainerSize = true) { Add((addContainerSize ? sizeof(T) : 0) + (int)vec.mAllocSize * sizeof(T) + (int)vec.size() * sizeof(typename std::remove_pointer::type)); //-V220 } template void AddVecPtr(const StringView& name, const Array& vec, bool addContainerSize = true) { Add(name, (addContainerSize ? sizeof(T) : 0) + (int)vec.mAllocSize * sizeof(T) + (int)vec.size() * sizeof(typename std::remove_pointer::type)); //-V220 } template void AddMap(const StringView& name, const T& map, bool addContainerSize = true) { Add(name, (addContainerSize ? sizeof(T) : 0) + map.mAllocSize * (sizeof(typename T::EntryPair) + sizeof(typename T::int_cosize))); } template void AddMap(const T& map, bool addContainerSize = true) { Add((addContainerSize ? sizeof(T) : 0) + map.mAllocSize * (sizeof(typename T::EntryPair) + sizeof(typename T::int_cosize))); } template void AddHashSet(const StringView& name, const T& map, bool addContainerSize = true) { Add(name, (addContainerSize ? sizeof(T) : 0) + map.mAllocSize * (sizeof(typename T::Entry) + sizeof(typename T::int_cosize))); } template void AddHashSet(const T& map, bool addContainerSize = true) { Add((addContainerSize ? sizeof(T) : 0) + map.mAllocSize * (sizeof(typename T::Entry) + sizeof(typename T::int_cosize))); } void AddStr(const StringImpl& str, bool addContainerSize = true) { Add((addContainerSize ? sizeof(StringImpl) : 0) + (int)str.GetAllocSize()); } void AddStr(const StringView& name, const StringImpl& str, bool addContainerSize = true) { Add(name, (addContainerSize ? sizeof(StringImpl) : 0) + (int)str.GetAllocSize()); } void EndSection(); void Report(); template void AddBumpAlloc(const StringView& name, const T& alloc) { BeginSection(name); int usedSize = alloc.CalcUsedSize(); #ifdef BUMPALLOC_TRACKALLOCS T* allocPtr = (T*)&alloc; int usedSizeLeft = usedSize; Array entries; for (const auto& kv : allocPtr->mTrackedAllocs) { const char* str = kv.mKey.c_str(); BumpAllocTrackedEntry trackedEntry = kv.mValue; String name; if (strncmp(str, "class ", 6) == 0) name = str + 6; else if (strncmp(str, "struct ", 7) == 0) name = str + 7; else name = str; BeginSection(name); mCurEntry->mSize += trackedEntry.mSize; mCurEntry->mCount += trackedEntry.mCount; EndSection(); usedSizeLeft -= trackedEntry.mSize; } if (usedSizeLeft > 0) Add("Unaccounted", usedSizeLeft); #else Add("Used", usedSize); #endif Add("Waste", alloc.GetAllocSize() - usedSize); Add("Unused", alloc.GetTotalAllocSize() - alloc.GetAllocSize()); EndSection(); } }; class AutoMemReporter { public: MemReporter* mMemReporter; public: AutoMemReporter(MemReporter* memReporter, const StringImpl& name) { mMemReporter = memReporter; mMemReporter->BeginSection(name); } ~AutoMemReporter() { mMemReporter->EndSection(); } }; NS_BF_END