ecere/com/instance; containers: MemTracking code
authorJerome St-Louis <jerome@ecere.com>
Wed, 9 Dec 2015 22:30:29 +0000 (17:30 -0500)
committerJerome St-Louis <jerome@ecere.com>
Mon, 21 Dec 2015 19:03:45 +0000 (14:03 -0500)
ecere/src/com/containers/AVLTree.ec
ecere/src/com/containers/Array.ec
ecere/src/com/containers/CustomAVLTree.ec
ecere/src/com/instance.ec

index 613c7b4..81d1e45 100644 (file)
@@ -29,6 +29,7 @@ public class AVLTree<class AT> : CustomAVLTree<BT = AVLNode<AT>, KT = AT, T = AT
    AVLNode<AT> Add(AT value)
    {
       AVLNode<AT> node;
+      // TODO: Optimize this here to use FindEx/AddEx...
       if(class(AT).type == structClass)
       {
          node = (AVLNode<AT>)new0 byte[sizeof(class AVLNode) + class(AT).structSize - sizeof(node.key)];
index 87eca14..07397cf 100644 (file)
@@ -2,6 +2,10 @@ namespace com;
 
 import "Container"
 
+#ifdef _DEBUG
+// #define MEMTRACKING
+#endif
+
 default:
 extern int __ecereVMethodID_class_OnUnserialize;
 private:
@@ -150,6 +154,13 @@ public:
             else if(value > count)
                memset((byte *)array + count * class(T).typeSize, 0, (value - count) * class(T).typeSize);
             count = value;
+#if defined(_DEBUG) && !defined(MEMINFO) && defined(MEMTRACKING)
+            if(array)
+            {
+               MemBlock block = (MemBlock)((byte *)array - sizeof(class MemBlock));
+               block._class = class(T);
+            }
+#endif
          }
       }
    }
index 6938a5b..3db7c64 100644 (file)
@@ -598,6 +598,7 @@ public:
 
    BT GetAtPosition(const KT pos, bool create, bool * justAdded)
    {
+      // TODO: FindEx / AddEx & create nodes if create is true?
       return root ? root.Find(class(KT), pos) : null;
    }
 }
index 871a04d..24e718e 100644 (file)
@@ -31,6 +31,11 @@ import "Mutex"
 #define REDZONE 0
 #endif
 
+
+#ifdef _DEBUG
+// #define MEMTRACKING
+#endif
+
 #ifdef MEMINFO
 import "Thread"
 static define MAX_MEMORY_LOC = 40;
@@ -711,6 +716,9 @@ private class MemBlock : struct
    MemBlock prev, next;
    MemPart part;
    uint size;
+#if defined(_DEBUG) && !defined(MEMINFO) && defined(MEMTRACKING)
+   Class _class;
+#endif
 };
 
 private class MemPart : struct
@@ -1227,6 +1235,9 @@ static void * _mymalloc(unsigned int size)
          block = pools[p].Add();
          if(block)
          {
+#if defined(_DEBUG) && defined(MEMTRACKING)
+            block._class = null;
+#endif
             block.size = size;
             pools[p].usedSpace += size;
          }
@@ -1239,6 +1250,9 @@ static void * _mymalloc(unsigned int size)
             TOTAL_MEM += sizeof(class MemBlock) + size;
             OUTSIDE_MEM += sizeof(class MemBlock) + size;
             block.part = null;
+#if defined(_DEBUG) && defined(MEMTRACKING)
+            block._class = null;
+#endif
             block.size = size;
          }
       }
@@ -4583,6 +4597,14 @@ public dllexport void * eInstance_New(Class _class)
       allocateClass = null;
    memMutex.Release();
 #endif
+
+#if defined(_DEBUG) && !defined(MEMINFO) && defined(MEMTRACKING)
+      {
+         MemBlock block = (MemBlock)((byte *)instance - sizeof(class MemBlock));
+         block._class = _class;
+      }
+#endif
+
       if(_class.type == normalClass)
       {
          instance._class = _class;
@@ -7227,3 +7249,77 @@ public uint16 * UTF8toUTF16(const char * source, int * wordCount)
 }
 
 namespace com;
+
+#if defined(_DEBUG) && !defined(MEMINFO) && defined(MEMTRACKING)
+import "Map"
+
+Map<Class, int> blocksByClass { };
+#endif
+
+public void queryMemInfo(char * string)
+{
+#if defined(_DEBUG) && !defined(MEMINFO) && defined(MEMTRACKING)
+   char s[1024];
+   int p;
+   uint numBlocks = 0;
+   //uintsize nonClassBytes = 0;
+   sprintf(s, "Total System Memory Usage: %.02f\n", TOTAL_MEM / 1048576.0f);
+   strcat(string, s);
+
+   for(p = 0; pools && p < NUM_POOLS; p++)
+   {
+      BlockPool * pool = &pools[p];
+      if(pool->totalSize)
+      {
+         numBlocks += pool->totalSize;
+         sprintf(s, "%8d bytes: %d blocks in %d parts (%.02f mb used; taking up %.02f mb space)\n",
+            pool->blockSize, pool->numBlocks, pool->numParts, pool->usedSpace / 1048576.0f, pool->totalSize * pool->blockSpace / 1048576.0f);
+         strcat(string, s);
+      }
+   }
+/*
+
+   blocksByClass.Free();
+   memMutex.Wait();
+   for(p = 0; pools && p < NUM_POOLS; p++)
+   {
+      BlockPool * pool = &pools[p];
+      MemBlock block;
+      for(block = pool->first; block; block = block.next)
+      {
+         Class c = block._class;
+         blocksByClass[c]++;
+         if(!c)
+            nonClassBytes += block.size;
+      }
+   }
+   memMutex.Release();
+
+   //for(c : blocksByClass)
+   {
+      MapIterator<Class, int> it { map = blocksByClass };
+      while(it.Next())
+      {
+         int c = it.data;
+         Class _class = it.key; //&c;
+         uintsize size = _class ? _class.structSize : nonClassBytes;
+         float totalSize = (float)size * (_class ? c : 1) / 1048576.0f;
+         if(totalSize > 1)
+         {
+            sprintf(s, "%s (%d bytes): %d instances (%.02f mb used)\n", _class ? _class.name : "(none)", (int)size, c, totalSize);
+            strcat(string, s);
+         }
+      }
+   }
+*/
+   sprintf(s, "Non-pooled memory: %.02f\n", OUTSIDE_MEM / 1048576.0f);
+   strcat(string, s);
+   sprintf(s, "Total Blocks Count: %d (%.02f mb overhead)\n", numBlocks, (float)sizeof(struct MemBlock) * numBlocks / 1048576.0f);
+   strcat(string, s);
+#ifdef MEMORYGUARD
+   sprintf(s, "MemoryGuard: %d blocks (%.02f mb RedZone, %.02f mb MemInfo)\n", memBlocks.count,
+      numBlocks * 2 * REDZONE / 1048576.0f, sizeof(struct MemInfo) * memBlocks.count / 1048576.0f);
+   strcat(string, s);
+#endif
+#endif
+}