فهرست منبع

Memory allocations are now properly counted accross multiple threads

Marko Pintera 12 سال پیش
والد
کامیت
9f381b82a4
4فایلهای تغییر یافته به همراه44 افزوده شده و 19 حذف شده
  1. 8 8
      CamelotCore/Source/CmCPUProfiler.cpp
  2. 34 8
      CamelotUtility/Include/CmMemoryAllocator.h
  3. 2 2
      CamelotUtility/Source/CmMemoryAllocator.cpp
  4. 0 1
      TextOpts.txt

+ 8 - 8
CamelotCore/Source/CmCPUProfiler.cpp

@@ -66,8 +66,8 @@ namespace CamelotFramework
 
 	void CPUProfiler::ProfileData::beginSample()
 	{
-		memAllocs = MemoryCounter::Allocs.load();
-		memFrees = MemoryCounter::Frees.load();
+		memAllocs = MemoryCounter::getNumAllocs();
+		memFrees = MemoryCounter::getNumFrees();
 
 		timer.reset();
 		timer.start();
@@ -77,8 +77,8 @@ namespace CamelotFramework
 	{
 		timer.stop();
 
-		UINT64 numAllocs = MemoryCounter::Allocs.load() - memAllocs;
-		UINT64 numFrees = MemoryCounter::Frees.load() - memFrees;
+		UINT64 numAllocs = MemoryCounter::getNumAllocs() - memAllocs;
+		UINT64 numFrees = MemoryCounter::getNumFrees() - memFrees;
 
 		samples.push_back(ProfileSample(timer.time, numAllocs, numFrees));
 	}
@@ -91,8 +91,8 @@ namespace CamelotFramework
 
 	void CPUProfiler::PreciseProfileData::beginSample()
 	{
-		memAllocs = MemoryCounter::Allocs.load();
-		memFrees = MemoryCounter::Frees.load();
+		memAllocs = MemoryCounter::getNumAllocs();
+		memFrees = MemoryCounter::getNumFrees();
 
 		timer.reset();
 		timer.start();
@@ -102,8 +102,8 @@ namespace CamelotFramework
 	{
 		timer.stop();
 
-		UINT64 numAllocs = MemoryCounter::Allocs.load() - memAllocs;
-		UINT64 numFrees = MemoryCounter::Frees.load() - memFrees;
+		UINT64 numAllocs = MemoryCounter::getNumAllocs() - memAllocs;
+		UINT64 numFrees = MemoryCounter::getNumFrees() - memFrees;
 
 		samples.push_back(PreciseProfileSample(timer.cycles, numAllocs, numFrees));
 	}

+ 34 - 8
CamelotUtility/Include/CmMemoryAllocator.h

@@ -8,11 +8,37 @@
 
 namespace CamelotFramework
 {
-	class CM_UTILITY_EXPORT MemoryCounter
+	class MemoryAllocatorBase;
+
+	class MemoryCounter
 	{
 	public:
-		static std::atomic_uint64_t Allocs;
-		static std::atomic_uint64_t Frees;
+		static CM_UTILITY_EXPORT UINT64 getNumAllocs()
+		{
+			return Allocs;
+		}
+
+		static CM_UTILITY_EXPORT UINT64 getNumFrees()
+		{
+			return Frees;
+		}
+		
+	private:
+		friend class MemoryAllocatorBase;
+
+		// Threadlocal data can't be exported, so some magic to make it accessible from MemoryAllocator
+		static CM_UTILITY_EXPORT void incAllocCount() { Allocs++; }
+		static CM_UTILITY_EXPORT void incFreeCount() { Frees++; }
+
+		static CM_THREADLOCAL UINT64 Allocs;
+		static CM_THREADLOCAL UINT64 Frees;
+	};
+
+	class MemoryAllocatorBase
+	{
+	protected:
+		static void incAllocCount() { MemoryCounter::incAllocCount(); }
+		static void incFreeCount() { MemoryCounter::incFreeCount(); }
 	};
 
 	/**
@@ -20,13 +46,13 @@ namespace CamelotFramework
 	 * 			Specialize for specific categories as needed.
 	 */
 	template<class T>
-	class MemoryAllocator
+	class MemoryAllocator : public MemoryAllocatorBase
 	{
 	public:
 		static inline void* allocate(UINT32 bytes)
 		{
 #if CM_PROFILING_ENABLED
-			MemoryCounter::Allocs++;
+			incAllocCount();
 #endif
 
 			return malloc(bytes);
@@ -35,7 +61,7 @@ namespace CamelotFramework
 		static inline void* allocateArray(UINT32 bytes, UINT32 count)
 		{
 #if CM_PROFILING_ENABLED
-			MemoryCounter::Allocs++;
+			incAllocCount();
 #endif
 
 			return malloc(bytes * count);
@@ -44,7 +70,7 @@ namespace CamelotFramework
 		static inline void free(void* ptr)
 		{
 #if CM_PROFILING_ENABLED
-			MemoryCounter::Frees++;
+			incFreeCount();
 #endif
 
 			::free(ptr);
@@ -53,7 +79,7 @@ namespace CamelotFramework
 		static inline void freeArray(void* ptr, UINT32 count)
 		{
 #if CM_PROFILING_ENABLED
-			MemoryCounter::Frees++;
+			incFreeCount();
 #endif
 
 			::free(ptr);

+ 2 - 2
CamelotUtility/Source/CmMemoryAllocator.cpp

@@ -2,6 +2,6 @@
 
 namespace CamelotFramework
 {
-	std::atomic_uint64_t MemoryCounter::Allocs = 0;
-	std::atomic_uint64_t MemoryCounter::Frees = 0;
+	UINT64 MemoryCounter::Allocs = 0;
+	UINT64 MemoryCounter::Frees = 0;
 }

+ 0 - 1
TextOpts.txt

@@ -2,7 +2,6 @@ Make sure to also update TextSprite and ImageSprite and anything else in UpdateM
 
 TODO: Fix allocation counter as it doesn't work properly between multiple threads
 TODO: Get rid of TextUtility and make all text generation happen in TextData constructor. Get rid of TextData shared_ptr as it just causes an unnecessary allocation.
-TODO: MultiLine text doesn't work and possibly input/selection
 TODO: Ensure that buffers in TextData actually handle multiple threads properly (THREADLOCAL?)
 
 Performance stats: