[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [26158] trunk/blender: Added a new notifyer, NC_SPACE_CHANGED, to signal an editor that

Joseph Eagar joeedh at gmail.com
Thu Jan 21 04:09:02 CET 2010


Revision: 26158
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=26158
Author:   joeedh
Date:     2010-01-21 04:08:57 +0100 (Thu, 21 Jan 2010)

Log Message:
-----------
Added a new notifyer, NC_SPACE_CHANGED, to signal an editor that
replaces another so it can do updates (e.g. dopesheet editor can
sync channel selection).

Also coded a simple optimization for allocating small objects,
based on mempools.  It's #ifdef'd out, you can enabled it by 
defining OPTIMIZE_SMALL_BLOCKS (e.g. adding -DDOPTIMIZE_SMALL_BLOCKS to
your compiler flags).

We suffer from a great deal of performance loss from the system allocator
(vgroups, ghash, edgehash, the singly-linked list implementation in blenlib,
editmesh, and likely a great many areas I'm forgetting), and this is the 
common solution for handling the many-small-objects problem.  It's not
really production-ready yet (it's long-term memory consequencers need to
be profiled first, and the implementation tweaked as necassary), but for
people on systems with slow system allocators it's worth trying.

Note that since this creates a guardedalloc<->blenlib link, the build systems
need to be updated accordingly (I've already done this for scons, though I'm
not sure if the player builds).

Modified Paths:
--------------
    trunk/blender/intern/guardedalloc/intern/mallocn.c
    trunk/blender/source/blender/blenkernel/intern/BME_Customdata.c
    trunk/blender/source/blender/blenkernel/intern/BME_mesh.c
    trunk/blender/source/blender/blenkernel/intern/customdata.c
    trunk/blender/source/blender/blenlib/BLI_mempool.h
    trunk/blender/source/blender/blenlib/intern/BLI_mempool.c
    trunk/blender/source/blender/editors/screen/area.c
    trunk/blender/source/blender/editors/space_action/space_action.c
    trunk/blender/source/blender/makesdna/intern/SConscript
    trunk/blender/source/blender/makesrna/intern/SConscript
    trunk/blender/source/blender/windowmanager/WM_types.h

Modified: trunk/blender/intern/guardedalloc/intern/mallocn.c
===================================================================
--- trunk/blender/intern/guardedalloc/intern/mallocn.c	2010-01-21 02:10:50 UTC (rev 26157)
+++ trunk/blender/intern/guardedalloc/intern/mallocn.c	2010-01-21 03:08:57 UTC (rev 26158)
@@ -37,6 +37,8 @@
 #include <string.h>	/* memcpy */
 #include <stdarg.h>
 
+#include "../../../source/blender/blenlib/BLI_mempool.h"
+
 /* mmap exception */
 #if defined(WIN32)
 #include <sys/types.h>
@@ -138,6 +140,40 @@
 /* implementation                                                        */
 /* --------------------------------------------------------------------- */
 
+#ifdef OPTIMIZE_SMALL_BLOCKS
+
+/*allocator for small objects
+
+  basic strategy: most slowdowns from overuse of the system allocator tends
+  to be from relatively small allocations.
+*/
+
+/*this is a little bit bigger then it perhaps needs to be, to accomodate vgroup
+  allocations (which are one system alloc per vertex of a mesh, and is a major
+  source of performance loss)*/
+#define SMALL_BLOCK_LIMIT	1024
+#define POOL_CHUNK_SIZE		512 /*size in number of elements, not bytes*/
+
+static BLI_mempool *alloc_pools[SMALL_BLOCK_LIMIT+sizeof(MemHead)+sizeof(MemTail)] = {NULL,};
+
+static void *mempool_alloc_mem(int size) {
+	size += sizeof(MemHead)+sizeof(MemTail);
+
+	if (!alloc_pools[size]) {
+		alloc_pools[size] = BLI_mempool_create(size, 1, POOL_CHUNK_SIZE, 1);
+	}
+	
+	return BLI_mempool_alloc(alloc_pools[size]);
+}
+
+static void mempool_free(void *mem, int size) {
+	size += sizeof(MemHead)+sizeof(MemTail);
+
+	BLI_mempool_free(alloc_pools[size], mem);
+}
+
+#endif
+
 static void print_error(const char *str, ...)
 {
 	char buf[1024];
@@ -254,7 +290,14 @@
 
 	len = (len + 3 ) & ~3; 	/* allocate in units of 4 */
 	
+#ifdef OPTIMIZE_SMALL_BLOCKS
+	if (len < SMALL_BLOCK_LIMIT)
+		memh= mempool_alloc_mem(len);
+	else
+		memh= (MemHead *)malloc(len+sizeof(MemHead)+sizeof(MemTail));
+#else
 	memh= (MemHead *)malloc(len+sizeof(MemHead)+sizeof(MemTail));
+#endif
 
 	if(memh) {
 		make_memhead_header(memh, len, str);
@@ -276,7 +319,16 @@
 
 	len = (len + 3 ) & ~3; 	/* allocate in units of 4 */
 
+#ifdef OPTIMIZE_SMALL_BLOCKS
+	if (len < SMALL_BLOCK_LIMIT) {
+		memh= mempool_alloc_mem(len);
+		memset(memh, 0, len+sizeof(MemHead)+sizeof(MemTail));
+	} else {
+		memh= (MemHead *)calloc(len+sizeof(MemHead)+sizeof(MemTail),1);
+	}
+#else
 	memh= (MemHead *)calloc(len+sizeof(MemHead)+sizeof(MemTail),1);
+#endif
 
 	if(memh) {
 		make_memhead_header(memh, len, str);
@@ -629,6 +681,11 @@
         if (munmap(memh, memh->len + sizeof(MemHead) + sizeof(MemTail)))
             printf("Couldn't unmap memory %s\n", memh->name);
     }
+#ifdef OPTIMIZE_SMALL_BLOCKS
+	else if (memh->len < SMALL_BLOCK_LIMIT) {
+		mempool_free(memh, memh->len);
+	}
+#endif
     else {
 		if(malloc_debug_memset && memh->len)
 			memset(memh+1, 255, memh->len);

Modified: trunk/blender/source/blender/blenkernel/intern/BME_Customdata.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/BME_Customdata.c	2010-01-21 02:10:50 UTC (rev 26157)
+++ trunk/blender/source/blender/blenkernel/intern/BME_Customdata.c	2010-01-21 03:08:57 UTC (rev 26158)
@@ -84,7 +84,7 @@
 	if(data->totlayer){
 		/*alloc memory*/
 		data->layers = MEM_callocN(sizeof(BME_CustomDataLayer)*data->totlayer, "BMesh Custom Data Layers");
-		data->pool = BLI_mempool_create(data->totsize, initalloc, initalloc);
+		data->pool = BLI_mempool_create(data->totsize, initalloc, initalloc, 0);
 		/*initialize layer data*/
 		for(i=0; i < BME_CD_NUMTYPES; i++){
 			if(init->layout[i]){

Modified: trunk/blender/source/blender/blenkernel/intern/BME_mesh.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/BME_mesh.c	2010-01-21 02:10:50 UTC (rev 26157)
+++ trunk/blender/source/blender/blenkernel/intern/BME_mesh.c	2010-01-21 03:08:57 UTC (rev 26158)
@@ -55,10 +55,10 @@
 	/*allocate the structure*/
 	BME_Mesh *bm = MEM_callocN(sizeof(BME_Mesh),"BMesh");
 	/*allocate the memory pools for the mesh elements*/
-	bm->vpool = BLI_mempool_create(sizeof(BME_Vert), allocsize[0], allocsize[0]);
-	bm->epool = BLI_mempool_create(sizeof(BME_Edge), allocsize[1], allocsize[1]);
-	bm->lpool = BLI_mempool_create(sizeof(BME_Loop), allocsize[2], allocsize[2]);
-	bm->ppool = BLI_mempool_create(sizeof(BME_Poly), allocsize[3], allocsize[3]);
+	bm->vpool = BLI_mempool_create(sizeof(BME_Vert), allocsize[0], allocsize[0], 0);
+	bm->epool = BLI_mempool_create(sizeof(BME_Edge), allocsize[1], allocsize[1], 0);
+	bm->lpool = BLI_mempool_create(sizeof(BME_Loop), allocsize[2], allocsize[2], 0);
+	bm->ppool = BLI_mempool_create(sizeof(BME_Poly), allocsize[3], allocsize[3], 0);
 	return bm;
 }
 /*	

Modified: trunk/blender/source/blender/blenkernel/intern/customdata.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/customdata.c	2010-01-21 02:10:50 UTC (rev 26157)
+++ trunk/blender/source/blender/blenkernel/intern/customdata.c	2010-01-21 03:08:57 UTC (rev 26158)
@@ -1922,7 +1922,7 @@
 
 
 void CustomData_bmesh_init_pool(CustomData *data, int allocsize){
-	if(data->totlayer)data->pool = BLI_mempool_create(data->totsize, allocsize, allocsize);
+	if(data->totlayer)data->pool = BLI_mempool_create(data->totsize, allocsize, allocsize, 0);
 }
 
 void CustomData_bmesh_free_block(CustomData *data, void **block)

Modified: trunk/blender/source/blender/blenlib/BLI_mempool.h
===================================================================
--- trunk/blender/source/blender/blenlib/BLI_mempool.h	2010-01-21 02:10:50 UTC (rev 26157)
+++ trunk/blender/source/blender/blenlib/BLI_mempool.h	2010-01-21 03:08:57 UTC (rev 26158)
@@ -34,7 +34,7 @@
 struct BLI_mempool;
 typedef struct BLI_mempool BLI_mempool;
 
-BLI_mempool *BLI_mempool_create(int esize, int tote, int pchunk);
+BLI_mempool *BLI_mempool_create(int esize, int tote, int pchunk, int use_sysmalloc);
 void *BLI_mempool_alloc(BLI_mempool *pool);
 void *BLI_mempool_calloc(BLI_mempool *pool);
 void BLI_mempool_free(BLI_mempool *pool, void *addr);

Modified: trunk/blender/source/blender/blenlib/intern/BLI_mempool.c
===================================================================
--- trunk/blender/source/blender/blenlib/intern/BLI_mempool.c	2010-01-21 02:10:50 UTC (rev 26157)
+++ trunk/blender/source/blender/blenlib/intern/BLI_mempool.c	2010-01-21 03:08:57 UTC (rev 26158)
@@ -49,9 +49,11 @@
 	struct ListBase chunks;
 	int esize, csize, pchunk;		/*size of elements and chunks in bytes and number of elements per chunk*/
 	struct BLI_freenode	*free;		/*free element list. Interleaved into chunk datas.*/
+	int totalloc, totused; /*total number of elements allocated in total, and currently in use*/
+	int use_sysmalloc;
 }BLI_mempool;
 
-BLI_mempool *BLI_mempool_create(int esize, int tote, int pchunk)
+BLI_mempool *BLI_mempool_create(int esize, int tote, int pchunk, int use_sysmalloc)
 {	BLI_mempool  *pool = NULL;
 	BLI_freenode *lasttail = NULL, *curnode = NULL;
 	int i,j, maxchunks;
@@ -61,19 +63,20 @@
 		esize = sizeof(void*);
 	
 	/*allocate the pool structure*/
-	pool = MEM_mallocN(sizeof(BLI_mempool),"memory pool");
+	pool = use_sysmalloc ? malloc(sizeof(BLI_mempool)) : MEM_mallocN(sizeof(BLI_mempool), "memory pool");
 	pool->esize = esize;
+	pool->use_sysmalloc = use_sysmalloc;
 	pool->pchunk = pchunk;	
 	pool->csize = esize * pchunk;
 	pool->chunks.first = pool->chunks.last = NULL;
 	
-	maxchunks = tote / pchunk;
+	maxchunks = tote / pchunk + 1;
 	
 	/*allocate the actual chunks*/
 	for(i=0; i < maxchunks; i++){
-		BLI_mempool_chunk *mpchunk = MEM_mallocN(sizeof(BLI_mempool_chunk), "BLI_Mempool Chunk");
+		BLI_mempool_chunk *mpchunk = use_sysmalloc ? malloc(sizeof(BLI_mempool_chunk)) : MEM_mallocN(sizeof(BLI_mempool_chunk), "BLI_Mempool Chunk");
 		mpchunk->next = mpchunk->prev = NULL;
-		mpchunk->data = MEM_mallocN(pool->csize, "BLI Mempool Chunk Data");
+		mpchunk->data = use_sysmalloc ? malloc(pool->csize) : MEM_mallocN(pool->csize, "BLI Mempool Chunk Data");
 		BLI_addtail(&(pool->chunks), mpchunk);
 		
 		if(i==0) pool->free = mpchunk->data; /*start of the list*/
@@ -87,6 +90,8 @@
 		if(lasttail) lasttail->next = mpchunk->data;
 		/*set the end of this chunks memoryy to the new tail for next iteration*/
 		lasttail = curnode;
+
+		pool->totalloc += pool->pchunk;
 	}
 	/*terminate the list*/
 	curnode->next = NULL;
@@ -98,11 +103,13 @@
 	char *addr=NULL;
 	int j;
 
+	pool->totused++;
+
 	if(!(pool->free)){
 		/*need to allocate a new chunk*/
-		BLI_mempool_chunk *mpchunk = MEM_mallocN(sizeof(BLI_mempool_chunk), "BLI_Mempool Chunk");
+		BLI_mempool_chunk *mpchunk = pool->use_sysmalloc ? malloc(sizeof(BLI_mempool_chunk)) :  MEM_mallocN(sizeof(BLI_mempool_chunk), "BLI_Mempool Chunk");
 		mpchunk->next = mpchunk->prev = NULL;
-		mpchunk->data = MEM_mallocN(pool->csize, "BLI_Mempool Chunk Data");
+		mpchunk->data = pool->use_sysmalloc ? malloc(pool->csize) : MEM_mallocN(pool->csize, "BLI_Mempool Chunk Data");
 		BLI_addtail(&(pool->chunks), mpchunk);
 
 		pool->free = mpchunk->data; /*start of the list*/
@@ -112,6 +119,8 @@
 			curnode->next = (BLI_freenode*)addr;
 		}
 		curnode->next = NULL; /*terminate the list*/
+
+		pool->totalloc += pool->pchunk;
 	}
 
 	retval = pool->free;
@@ -128,16 +137,48 @@
 }
 
 
-
 void BLI_mempool_free(BLI_mempool *pool, void *addr){ //doesnt protect against double frees, dont be stupid!
 	BLI_freenode *newhead = addr;
+	BLI_freenode *curnode=NULL;
+	char *tmpaddr=NULL;
+	int i;
+
 	newhead->next = pool->free;
 	pool->free = newhead;
+
+	pool->totused--;
+
+	/*nothing is in use; free all the chunks except the first*/
+	if (pool->totused == 0) {
+		BLI_mempool_chunk *mpchunk=NULL, *first;
+
+		first = pool->chunks.first;
+		BLI_remlink(&pool->chunks, first);
+
+		for(mpchunk = pool->chunks.first; mpchunk; mpchunk = mpchunk->next) 
+			pool->use_sysmalloc ? free(mpchunk->data) : MEM_freeN(mpchunk->data);
+		
+		pool->use_sysmalloc ? BLI_freelist(&(pool->chunks)) : BLI_freelistN(&(pool->chunks));
+		
+		BLI_addtail(&pool->chunks, first);
+		pool->totalloc = pool->pchunk;
+
+		pool->free = first->data; /*start of the list*/
+		for(tmpaddr = first->data, i=0; i < pool->pchunk; i++){
+			curnode = ((BLI_freenode*)tmpaddr);
+			tmpaddr += pool->esize;
+			curnode->next = (BLI_freenode*)tmpaddr;
+		}

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list