From e905bad9816b19fa0004a54d2cda7ba840ca6b93 Mon Sep 17 00:00:00 2001 From: Georg Hopp Date: Fri, 13 Jun 2014 15:28:31 +0100 Subject: [PATCH] optimize allocation for GNU systems. That is allocate only blocks of a size malloc handles. --- src/memory.c | 139 ++++++++++++++++----------------------------------- 1 file changed, 43 insertions(+), 96 deletions(-) diff --git a/src/memory.c b/src/memory.c index 539fa10..f56f404 100644 --- a/src/memory.c +++ b/src/memory.c @@ -623,65 +623,13 @@ deleteElement(struct memSegment ** tree, struct memSegment * element) return del_node; } - -//static -//void -//traverse(struct memSegment * tree, void (*cb)(struct memSegment *, int)) -//{ -// struct memSegment * previous = tree; -// struct memSegment * node = tree; -// int depth = 1; -// -// /* -// * I think this has something like O(n+log(n)) on a ballanced -// * tree because I have to traverse back the rightmost leaf to -// * the root to get a break condition. -// */ -// while (node) { -// /* -// * If we come from the right so nothing and go to our -// * next parent. -// */ -// if (previous == node->right) { -// previous = node; -// node = node->parent; -// depth--; -// continue; -// } -// -// if ((NULL == node->left || previous == node->left)) { -// /* -// * If there are no more elements to the left or we -// * came from the left, process data. -// */ -// cb(node, depth); -// previous = node; -// -// if (NULL != node->right) { -// node = node->right; -// depth++; -// } else { -// node = node->parent; -// depth--; -// } -// } else { -// /* -// * if there are more elements to the left go there. -// */ -// previous = node; -// node = node->left; -// depth++; -// } -// } -//} - static void post(struct memSegment * tree, void (*cb)(struct memSegment *, int)) { struct memSegment * previous = tree; struct memSegment * node = tree; - int depth = 1; + int depth = 1; /* * I think this has something like O(n+log(n)) on a ballanced @@ -732,42 +680,6 @@ post(struct memSegment * tree, void (*cb)(struct memSegment *, int)) } } -//void -//printElement(struct memSegment * node, int depth) -//{ -// int i; -// -// printf("%s %010zu:%p(%02d)", -// (node->color==rbRed)?"R":"B", -// node->size, -// node->ptr, -// depth); -// for (i=0; inext; -// while (NULL != node) { -// printf(" %s %010zu:%p(%02d)", -// (node->color==rbRed)?"R":"B", -// node->size, -// node->ptr, -// depth); -// for (i=0; inext; -// } -//} - -//void -//cleanup(struct memSegment * node, int depth) -//{ -// while (NULL != node) { -// struct memSegment * next = node->next; -// free(node); -// node = next; -// } -//} - static struct memSegment * segments = NULL; @@ -793,20 +705,55 @@ TR_reference(void * mem) } /* - * This will always allocate a multiple of PAGESIZE + * This tries to reflect the memory management behaviour of the + * GNU version of malloc. For other versions this might need + * to be changed to be optimal. + * + * However, GNU malloc keeps separate pools for each power of + * 2 memory size up to page size. So one page consists all of + * memory blocks of the same sizei (a power of 2). + * + * Also as far as I understand the smallest allocatable block is + * 8 bytes. At least the adresses are alwayse a multiple of 8. + * + * So lets say page size is 4096. There is nothing allocated + * right now. We allocate a block of 8 bytes. This will request + * a memory page from the OS. Then define it as a page containing + * 8 byte blocks and return the address of the first one of these. + * Any subsequent call to malloc for 8 bytes will return one of the + * blocks within this page as long as there are some left. + * + * So what we do here is up to page size round the request size up + * to the next power of 2 >= 8. + * Sizes greater then pagesize will be round up to the next + * multiple of pagesize. As far as I understand these are not + * pooled anyway. + * + * For now this assumes we are on a little endian machine. */ void * TR_malloc(size_t size) { - struct memSegment * seg = NULL; - //long psize = sysconf(_SC_PAGESIZE); - long psize = 64; + struct memSegment * seg = NULL; + long psize = sysconf(_SC_PAGESIZE); + size_t check; size += sizeof(struct memSegment); - /* allocate only blocks of a multiple of pagesize, similar to cbuf */ - size = (0>=size)?1:(0!=size%psize)?(size/psize)+1:size/psize; - size *= psize; + if (size > psize) { + if (0 != (size % psize)) { + // size if not a multiple of pagesize so bring it to one. + size = ((size / psize) + 1) * psize; + } + } else { + check = size >> 1; + check = (size | check) - check; + + if (check != size) { + // size is not a power of 2 so bring it to one. + size = ((size << 1) | size) - size; + } + } #ifdef MEM_OPT seg = findElement(segments, size);