Memory usage debugging: now with the -d debug option enabled, at the end
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Fri, 1 Feb 2008 12:14:15 +0000 (12:14 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Fri, 1 Feb 2008 12:14:15 +0000 (12:14 +0000)
of rendering it prints memory usage for images and all memory blocks.

intern/guardedalloc/MEM_guardedalloc.h
intern/guardedalloc/intern/mallocn.c
source/blender/blenkernel/BKE_image.h
source/blender/blenkernel/intern/image.c
source/blender/render/intern/source/convertblender.c

index 94276c0454aca442ab5ae7285d676f64dab28b25..73eddff7d8ace2492c3cac6e0d9cb14cb786ccca 100644 (file)
@@ -106,6 +106,9 @@ extern "C" {
        /** Print a list of the names and sizes of all allocated memory
         * blocks. */ 
        void MEM_printmemlist(void);
+
+       /** Print statistics about memory usage */
+       void MEM_printmemlist_stats(void);
        
        /** Set the callback function for error output. */
        void MEM_set_error_callback(void (*func)(char *));
index 413f4d8051496ca7c8c6a0fcbc40245edb40245e..c1ddfa71a1086b9cd327951a29a0204fc7770a39 100644 (file)
@@ -332,6 +332,91 @@ void *MEM_mapallocN(unsigned int len, const char *str)
 #endif
 }
 
+/* Memory statistics print */
+typedef struct MemPrintBlock {
+       const char *name;
+       unsigned long len;
+       int items;
+} MemPrintBlock;
+
+static int compare_name(const void *p1, const void *p2)
+{
+       const MemPrintBlock *pb1= (const MemPrintBlock*)p1;
+       const MemPrintBlock *pb2= (const MemPrintBlock*)p2;
+
+       return strcmp(pb1->name, pb2->name);
+}
+
+static int compare_len(const void *p1, const void *p2)
+{
+       const MemPrintBlock *pb1= (const MemPrintBlock*)p1;
+       const MemPrintBlock *pb2= (const MemPrintBlock*)p2;
+
+       if(pb1->len < pb2->len)
+               return 1;
+       else if(pb1->len == pb2->len)
+               return 0;
+       else
+               return -1;
+}
+
+void MEM_printmemlist_stats()
+{
+       MemHead *membl;
+       MemPrintBlock *pb, *printblock;
+       int totpb, a, b;
+
+       mem_lock_thread();
+
+       /* put memory blocks into array */
+       printblock= malloc(sizeof(MemPrintBlock)*totblock);
+
+       pb= printblock;
+       totpb= 0;
+
+       membl = membase->first;
+       if (membl) membl = MEMNEXT(membl);
+
+       while(membl) {
+               pb->name= membl->name;
+               pb->len= membl->len;
+               pb->items= 1;
+
+               totpb++;
+               pb++;
+
+               if(membl->next)
+                       membl= MEMNEXT(membl->next);
+               else break;
+       }
+
+       /* sort by name and add together blocks with the same name */
+       qsort(printblock, totpb, sizeof(MemPrintBlock), compare_name);
+       for(a=0, b=0; a<totpb; a++) {
+               if(a == b) {
+                       continue;
+               }
+               else if(strcmp(printblock[a].name, printblock[b].name) == 0) {
+                       printblock[b].len += printblock[a].len;
+                       printblock[b].items++;
+               }
+               else {
+                       b++;
+                       memcpy(&printblock[b], &printblock[a], sizeof(MemPrintBlock));
+               }
+       }
+       totpb= b+1;
+
+       /* sort by length and print */
+       qsort(printblock, totpb, sizeof(MemPrintBlock), compare_len);
+       printf("\ntotal memory len: %.3f MB\n", (double)mem_in_use/(double)(1024*1024));
+       for(a=0, pb=printblock; a<totpb; a++, pb++)
+               printf("%s items: %d, len: %.3f MB\n", pb->name, pb->items, (double)pb->len/(double)(1024*1024));
+
+       free(printblock);
+       
+       mem_unlock_thread();
+}
 
 /* Prints in python syntax for easy */
 static void MEM_printmemlist_internal( int pydict )
index ca34240cf2711d8bfc588cd2627d22a82c2ffd38..a584722031b117692e6ddb4cae11b24a4f1dcbeb 100644 (file)
@@ -148,6 +148,9 @@ void BKE_image_all_free_anim_ibufs(int except_frame);
 
 void BKE_image_memorypack(struct Image *ima);
 
+/* prints memory statistics for images */
+void BKE_image_print_memlist(void);
+
 #ifdef __cplusplus
 }
 #endif
index 0c45356eb0b17f1e07a91935876e57d4130ad711..3b7ab4951f6bd182433b7a654db3b361d442911f 100644 (file)
@@ -629,6 +629,47 @@ void free_old_images()
        }
 }
 
+static unsigned long image_mem_size(Image *ima)
+{
+       ImBuf *ibuf, *ibufm;
+       int level;
+       unsigned long size = 0;
+
+       size= 0;
+       for(ibuf= ima->ibufs.first; ibuf; ibuf= ibuf->next) {
+               if(ibuf->rect) size += MEM_allocN_len(ibuf->rect);
+               else if(ibuf->rect_float) size += MEM_allocN_len(ibuf->rect_float);
+
+               for(level=0; level<IB_MIPMAP_LEVELS; level++) {
+                       ibufm= ibuf->mipmap[level];
+                       if(ibufm) {
+                               if(ibufm->rect) size += MEM_allocN_len(ibufm->rect);
+                               else if(ibufm->rect_float) size += MEM_allocN_len(ibufm->rect_float);
+                       }
+               }
+       }
+
+       return size;
+}
+
+void BKE_image_print_memlist(void)
+{
+       Image *ima;
+       unsigned long size, totsize= 0;
+
+       for(ima= G.main->image.first; ima; ima= ima->id.next)
+               totsize += image_mem_size(ima);
+
+       printf("\ntotal image memory len: %.3lf MB\n", (double)totsize/(double)(1024*1024));
+
+       for(ima= G.main->image.first; ima; ima= ima->id.next) {
+               size= image_mem_size(ima);
+
+               if(size)
+                       printf("%s len: %.3f MB\n", ima->id.name+2, (double)size/(double)(1024*1024));
+       }
+}
+
 void BKE_image_free_all_textures(void)
 {
        Tex *tex;
index 38ae7fde1811d63c5c9e7b3aee3f25f585cf4e79..e4c62c1503421f3ce8eb8a242ed5ab5677eb792c 100644 (file)
@@ -4129,6 +4129,14 @@ void RE_Database_Free(Render *re)
 {
        Object *ob = NULL;
        LampRen *lar;
+       
+       /* statistics for debugging render memory usage */
+       if(G.f & G_DEBUG) {
+               if((re->r.scemode & R_PREVIEWBUTS)==0) {
+                       BKE_image_print_memlist();
+                       MEM_printmemlist_stats();
+               }
+       }
 
        /* FREE */