Commit bec6f38730fb96bc6401db8097744c3a13c2af8d

Authored by Georg Hopp
1 parent a92c8ac7

I do not use trees anymore within the optimized memory management. I realized th…

…at I can calculate the index of an array by the size and use stacks of memory segments under each array element. This should be much faster.
Showing 2 changed files with 122 additions and 289 deletions
@@ -27,6 +27,48 @@ @@ -27,6 +27,48 @@
27 27
28 #include <sys/types.h> 28 #include <sys/types.h>
29 29
  30 +/**
  31 + * I found this at stanford.edu:
  32 + * https://graphics.stanford.edu/~seander/bithacks.html#IntegerLogLookup
  33 + *
  34 + * Really cool way of dealing with this. The oneat stanford.edu is slightly
  35 + * different as ist deals only with 32bit values. I need a 64bit version
  36 + * because on a 64bit system size_t is also 64bit and thus it is possible
  37 + * to allocate that much amount of memory theoretically.
  38 + */
  39 +static
  40 +inline
  41 +int
  42 +bitwidth(size_t value)
  43 +{
  44 + static const char LogTable256[256] = {
  45 + -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
  46 +#define LT(n) n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n
  47 + LT(4), LT(5), LT(5), LT(6), LT(6), LT(6), LT(6),
  48 + LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7)
  49 + };
  50 +#undef LT
  51 +
  52 + int r; // r will be lg(v)
  53 + register size_t t1, t2, t3; // temporaries
  54 +
  55 + if ((t3 = value >> 32)) {
  56 + if ((t2 = t3 >> 16)) {
  57 + r = (t1 = t2 >> 8) ? 56 + LogTable256[t1] : 48 + LogTable256[t2];
  58 + } else {
  59 + r = (t1 = t3 >> 8) ? 40 + LogTable256[t1] : 32 + LogTable256[t3];
  60 + }
  61 + } else {
  62 + if ((t2 = value >> 16)) {
  63 + r = (t1 = t2 >> 8) ? 24 + LogTable256[t1] : 16 + LogTable256[t2];
  64 + } else {
  65 + r = (t1 = value >> 8) ? 8 + LogTable256[t1] : LogTable256[value];
  66 + }
  67 + }
  68 +
  69 + return r;
  70 +}
  71 +
30 void * TR_malloc(size_t); 72 void * TR_malloc(size_t);
31 void * TR_calloc(size_t, size_t); 73 void * TR_calloc(size_t, size_t);
32 void * TR_reference(void *); 74 void * TR_reference(void *);
@@ -53,310 +53,73 @@ @@ -53,310 +53,73 @@
53 #include <string.h> 53 #include <string.h>
54 #include <search.h> 54 #include <search.h>
55 #include <unistd.h> 55 #include <unistd.h>
  56 +#include <stdint.h>
56 57
57 #include "tr/memory.h" 58 #include "tr/memory.h"
58 -#include "tr/tree_macros.h"  
59 59
60 60
61 struct memSegment 61 struct memSegment
62 { 62 {
63 size_t ref_count; 63 size_t ref_count;
64 size_t size; 64 size_t size;
  65 + int idx;
65 void * ptr; 66 void * ptr;
66 67
67 - TR_rbColor color;  
68 -  
69 - struct memSegment * data;  
70 -  
71 struct memSegment * next; 68 struct memSegment * next;
72 - struct memSegment * last;  
73 -  
74 - struct memSegment * parent;  
75 - struct memSegment * left;  
76 - struct memSegment * right;  
77 }; 69 };
78 70
79 static 71 static
80 struct memSegment * 72 struct memSegment *
81 -newElement(size_t size) 73 +newElement(size_t size, int idx)
82 { 74 {
83 struct memSegment * element = malloc(size); 75 struct memSegment * element = malloc(size);
84 76
85 element->ref_count = 1; 77 element->ref_count = 1;
86 element->size = size; 78 element->size = size;
  79 + element->idx = idx;
87 element->ptr = (void*)element + sizeof(struct memSegment); 80 element->ptr = (void*)element + sizeof(struct memSegment);
88 81
89 - element->data = element;  
90 -  
91 element->next = NULL; 82 element->next = NULL;
92 - element->last = NULL;  
93 -  
94 - element->color = rbRed;  
95 - element->parent = NULL;  
96 - element->left = NULL;  
97 - element->right = NULL;  
98 83
99 return element; 84 return element;
100 } 85 }
101 86
102 #ifdef MEM_OPT 87 #ifdef MEM_OPT
103 -static  
104 -int  
105 -_memSegmentFindCompare(const void * a, const void * b)  
106 -{  
107 - struct memSegment * _a = (struct memSegment *)a;  
108 - size_t _b = *(size_t *)b;  
109 -  
110 - /*  
111 - * find the smallest bigger or equal size segment  
112 - */  
113 - return _a->size < _b ? -1  
114 - : _a->size > _b && _a->left && _a->left->size >= _b ? 1 : 0;  
115 -}  
116 -  
117 -static  
118 -int  
119 -_memSegmentCompare(const void * a, const void * b)  
120 -{  
121 - size_t _a = ((struct memSegment *)a)->size;  
122 - size_t _b = ((struct memSegment *)b)->size;  
123 -  
124 - return _a < _b ? -1 : _a > _b ? 1 : 0;  
125 -}  
126 -  
127 /** 88 /**
128 * insert element in tree 89 * insert element in tree
129 */ 90 */
130 static 91 static
  92 +inline
131 struct memSegment * 93 struct memSegment *
132 -insertElement(struct memSegment ** tree, struct memSegment * element) 94 +insertElement(struct memSegment ** stack, struct memSegment * element)
133 { 95 {
134 - struct memSegment * node = *tree;  
135 - struct memSegment * new_node = NULL;  
136 - int found;  
137 -  
138 - element->next = NULL;  
139 - element->last = NULL;  
140 -  
141 - element->color = rbRed;  
142 - element->parent = NULL;  
143 - element->left = NULL;  
144 - element->right = NULL;  
145 -  
146 - TR_TREE_FIND(node, element, found, _memSegmentCompare);  
147 -  
148 - // if tree is empty it's simple... :)  
149 - if (NULL == node) {  
150 - *tree = node = new_node = element;  
151 - } else {  
152 - // normal binary tree add....  
153 - if (found == 0) {  
154 - if (NULL == node->next) {  
155 - node->next = element;  
156 - node->last = element;  
157 - } else {  
158 - node->last->next = element;  
159 - node->last = element;  
160 - }  
161 - return node;  
162 - } else {  
163 - if (0 < found) {  
164 - node->left = element;  
165 - node->left->parent = node;  
166 - new_node = node = node->left;  
167 - } else {  
168 - node->right = element;  
169 - node->right->parent = node;  
170 - new_node = node = node->right; 96 + element->next = *stack;
  97 + *stack = element;
171 98
172 - }  
173 - }  
174 - }  
175 -  
176 - /*  
177 - * handle reballancing rb style  
178 - */  
179 - TR_TREE_BALANCE_INSERT(tree, node);  
180 -  
181 - return new_node; 99 + return element;
182 } 100 }
183 101
184 static 102 static
  103 +inline
185 struct memSegment * 104 struct memSegment *
186 -deleteElement(struct memSegment ** tree, size_t size) 105 +deleteElement(struct memSegment ** stack)
187 { 106 {
188 - struct memSegment * node = *tree;  
189 - struct memSegment * del_node;  
190 - struct memSegment * child;  
191 - struct memSegment * s;  
192 - int found;  
193 -  
194 - // find the relevant node and it's parent  
195 - TR_TREE_FIND(node, &size, found, _memSegmentFindCompare); 107 + struct memSegment * del_node = *stack;
196 108
197 - //while (node) {  
198 - if (found != 0) {  
199 - return NULL;  
200 - } else {  
201 - if (NULL != node->next) {  
202 - if (NULL != node->parent) {  
203 - if (node == node->parent->left) {  
204 - node->parent->left = node->next;  
205 - } else {  
206 - node->parent->right = node->next;  
207 - }  
208 - } else {  
209 - *tree = node->next;  
210 - }  
211 -  
212 - if (NULL != node->left) {  
213 - node->left->parent = node->next;  
214 - }  
215 -  
216 - if (NULL != node->right) {  
217 - node->right->parent = node->next;  
218 - }  
219 -  
220 - node->next->last = node->last;  
221 - node->next->color = node->color;  
222 - node->next->parent = node->parent;  
223 - node->next->left = node->left;  
224 - node->next->right = node->right;  
225 -  
226 - return node;  
227 - } 109 + if (*stack) {
  110 + *stack = (*stack)->next;
228 } 111 }
229 112
230 - del_node = node;  
231 -  
232 - // now our cases follows...the first one is the same as with  
233 - // simple binary search trees. Two non null children.  
234 -  
235 - // case 1: two children  
236 - if (NULL != node->left && NULL != node->right) {  
237 - struct memSegment * successor;  
238 - struct memSegment * tmpparent;  
239 - struct memSegment * tmpleft;  
240 - struct memSegment * tmpright;  
241 - TR_rbColor tmpcolor;  
242 -  
243 - TR_TREE_INORDER_SUCC(node, successor);  
244 - tmpparent = successor->parent;  
245 - tmpleft = successor->left;  
246 - tmpright = successor->right;  
247 - tmpcolor = successor->color;  
248 -  
249 - TR_TREE_REPLACE_NODE(tree, node, successor);  
250 -  
251 - successor->color = node->color;  
252 - successor->left = node->left;  
253 - successor->left->parent = successor;  
254 - // the right one might be successor...  
255 - if (node->right == successor) {  
256 - successor->right = node;  
257 - node->parent = successor;  
258 - } else {  
259 - successor->right = node->right;  
260 - node->right->parent = successor;  
261 - node->parent = tmpparent;  
262 - tmpparent->left = node;  
263 - }  
264 -  
265 - node->color = tmpcolor;  
266 - node->left = tmpleft;  
267 - node->right = tmpright;  
268 - }  
269 -  
270 - // Precondition: n has at most one non-null child.  
271 - child = (NULL == node->right) ? node->left : node->right;  
272 - TR_TREE_REPLACE_NODE(tree, node, child);  
273 -  
274 - // delete one child case  
275 - // TODO this is overly complex as simply derived from the function...  
276 - // maybe this can be simplified. Maybe not...check.  
277 - if (node->color == rbBlack) {  
278 - if (NULL != child && child->color == rbRed) {  
279 - child->color = rbBlack;  
280 - // done despite modifying tree itself if neccessary..  
281 - return del_node;  
282 - } else {  
283 - if (NULL != child) {  
284 - node = child;  
285 - } else {  
286 - node->color = rbBlack;  
287 - node->left = NULL;  
288 - node->right = NULL;  
289 - }  
290 - }  
291 - } else {  
292 - return del_node;  
293 - }  
294 -  
295 - TR_TREE_BALANCE_DELETE(tree, node, s);  
296 -  
297 - return del_node; 113 + return del_node;
298 } 114 }
299 115
300 -static  
301 -void  
302 -post(struct memSegment * tree, void (*cb)(struct memSegment *, int))  
303 -{  
304 - struct memSegment * previous = tree;  
305 - struct memSegment * node = tree;  
306 - int depth = 1;  
307 -  
308 - /*  
309 - * I think this has something like O(n+log(n)) on a ballanced  
310 - * tree because I have to traverse back the rightmost leaf to  
311 - * the root to get a break condition.  
312 - */  
313 - while (node) {  
314 - /*  
315 - * If we come from the right so nothing and go to our  
316 - * next parent.  
317 - */  
318 - if (((NULL == node->left || previous == node->left)  
319 - && NULL == node->right)  
320 - || previous == node->right) {  
321 -  
322 - struct memSegment * parent = node->parent;  
323 -  
324 - cb(node, depth);  
325 -  
326 - previous = node;  
327 - node = parent;  
328 - depth--;  
329 - continue;  
330 - } 116 +#define TR_MAX_MEM_IDX 1024
331 117
332 - if ((NULL == node->left || previous == node->left)) {  
333 - /*  
334 - * If there are no more elements to the left or we  
335 - * came from the left, process data.  
336 - */  
337 - previous = node;  
338 -  
339 - if (NULL != node->right) {  
340 - node = node->right;  
341 - depth++;  
342 - } else {  
343 - node = node->parent;  
344 - depth--;  
345 - }  
346 - } else {  
347 - /*  
348 - * if there are more elements to the left go there.  
349 - */  
350 - previous = node;  
351 - node = node->left;  
352 - depth++;  
353 - }  
354 - }  
355 -}  
356 -  
357 -struct memSegment * segments = NULL; 118 +struct memSegment * segments[TR_MAX_MEM_IDX] = {};
  119 +pthread_mutex_t TR_memop_lock = PTHREAD_MUTEX_INITIALIZER;
358 120
359 static 121 static
  122 +inline
360 void 123 void
361 segmentFree(struct memSegment * segment, int depth) 124 segmentFree(struct memSegment * segment, int depth)
362 { 125 {
@@ -378,8 +141,6 @@ TR_reference(void * mem) @@ -378,8 +141,6 @@ TR_reference(void * mem)
378 return mem; 141 return mem;
379 } 142 }
380 143
381 -pthread_mutex_t TR_memop_lock = PTHREAD_MUTEX_INITIALIZER;  
382 -  
383 /* 144 /*
384 * This tries to reflect the memory management behaviour of the 145 * This tries to reflect the memory management behaviour of the
385 * GNU version of malloc. For other versions this might need 146 * GNU version of malloc. For other versions this might need
@@ -410,41 +171,60 @@ pthread_mutex_t TR_memop_lock = PTHREAD_MUTEX_INITIALIZER; @@ -410,41 +171,60 @@ pthread_mutex_t TR_memop_lock = PTHREAD_MUTEX_INITIALIZER;
410 void * 171 void *
411 TR_malloc(size_t size) 172 TR_malloc(size_t size)
412 { 173 {
413 - struct memSegment * seg = NULL;  
414 - long psize = sysconf(_SC_PAGESIZE); 174 + struct memSegment * seg = NULL;
  175 + long psize = sysconf(_SC_PAGESIZE);
  176 + static int psize_width = 0;
  177 + int idx;
  178 +
  179 + if (psize_width == 0) psize_width = bitwidth(psize);
415 180
416 size += sizeof(struct memSegment); 181 size += sizeof(struct memSegment);
417 182
418 - if (size > psize) {  
419 - if (0 != (size % psize)) {  
420 - // size if not a multiple of pagesize so bring it to one.  
421 - size = ((size / psize) + 1) * psize;  
422 - }  
423 - } else {  
424 - if (size < 8) {  
425 - size = 8;  
426 - } else {  
427 - size_t check = size >> 4;  
428 - size_t mask = 0x1F; 183 +#define MIN_BITS 8
429 184
430 - while (check >>= 1) {  
431 - mask = (mask << 1) | 1;  
432 - } 185 + if (size >= psize) {
  186 + idx = size / psize;
433 187
434 - if (size != (size & ~(mask >> 1))) {  
435 - size = (size << 1) & ~mask;  
436 - }  
437 - }  
438 - } 188 + if (0 != (size % psize)) {
  189 + // size if not a multiple of pagesize so bring it to one.
  190 + size = (idx + 1) * psize;
  191 + idx++;
  192 + }
  193 +
  194 + idx += psize_width - MIN_BITS;
  195 + } else {
  196 + if (size <= 1 << (MIN_BITS - 1)) {
  197 + size = 1 << (MIN_BITS - 1);
  198 + idx = 0;
  199 + } else {
  200 + size_t mask;
  201 +
  202 + idx = bitwidth(size);
  203 + mask = (1 << (idx + 1)) - 1;
  204 + idx -= (MIN_BITS - 1);
  205 +
  206 + if (size != (size & ~(mask >> 1))) {
  207 + size = (size << 1) & ~mask;
  208 + idx++;
  209 + }
  210 + }
  211 + }
  212 +
  213 +#undef MIN_BITS
439 214
440 #ifdef MEM_OPT 215 #ifdef MEM_OPT
441 - pthread_mutex_lock(&TR_memop_lock);  
442 - seg = deleteElement(&segments, size);  
443 - pthread_mutex_unlock(&TR_memop_lock); 216 + if (idx < TR_MAX_MEM_IDX) {
  217 + pthread_mutex_lock(&TR_memop_lock);
  218 + seg = deleteElement(&(segments[idx]));
  219 + pthread_mutex_unlock(&TR_memop_lock);
  220 + } else
444 #endif 221 #endif
  222 + {
  223 + idx = -1;
  224 + }
445 225
446 if (NULL == seg) { 226 if (NULL == seg) {
447 - seg = newElement(size); 227 + seg = newElement(size, idx);
448 } 228 }
449 229
450 return seg->ptr; 230 return seg->ptr;
@@ -479,12 +259,15 @@ TR_free(void ** mem) @@ -479,12 +259,15 @@ TR_free(void ** mem)
479 seg->ref_count--; 259 seg->ref_count--;
480 } else { 260 } else {
481 #ifdef MEM_OPT 261 #ifdef MEM_OPT
482 - pthread_mutex_lock(&TR_memop_lock);  
483 - insertElement(&segments, seg);  
484 - pthread_mutex_unlock(&TR_memop_lock);  
485 -#else  
486 - free(seg); 262 + if (-1 != seg->idx) {
  263 + pthread_mutex_lock(&TR_memop_lock);
  264 + insertElement(&(segments[seg->idx]), seg);
  265 + pthread_mutex_unlock(&TR_memop_lock);
  266 + } else
487 #endif 267 #endif
  268 + {
  269 + free(seg);
  270 + }
488 } 271 }
489 272
490 *mem = NULL; 273 *mem = NULL;
@@ -508,7 +291,15 @@ void @@ -508,7 +291,15 @@ void
508 TR_cleanup() 291 TR_cleanup()
509 { 292 {
510 #ifdef MEM_OPT 293 #ifdef MEM_OPT
511 - post(segments, segmentFree); 294 + int i;
  295 +
  296 + for (i=0; i<TR_MAX_MEM_IDX; i++) {
  297 + while(segments[i]) {
  298 + struct memSegment * next = segments[i]->next;
  299 + free(segments[i]);
  300 + segments[i] = next;
  301 + }
  302 + }
512 #endif 303 #endif
513 } 304 }
514 305
Please register or login to post a comment