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 27
28 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 72 void * TR_malloc(size_t);
31 73 void * TR_calloc(size_t, size_t);
32 74 void * TR_reference(void *);
... ...
... ... @@ -53,310 +53,73 @@
53 53 #include <string.h>
54 54 #include <search.h>
55 55 #include <unistd.h>
  56 +#include <stdint.h>
56 57
57 58 #include "tr/memory.h"
58   -#include "tr/tree_macros.h"
59 59
60 60
61 61 struct memSegment
62 62 {
63 63 size_t ref_count;
64 64 size_t size;
  65 + int idx;
65 66 void * ptr;
66 67
67   - TR_rbColor color;
68   -
69   - struct memSegment * data;
70   -
71 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 71 static
80 72 struct memSegment *
81   -newElement(size_t size)
  73 +newElement(size_t size, int idx)
82 74 {
83 75 struct memSegment * element = malloc(size);
84 76
85 77 element->ref_count = 1;
86 78 element->size = size;
  79 + element->idx = idx;
87 80 element->ptr = (void*)element + sizeof(struct memSegment);
88 81
89   - element->data = element;
90   -
91 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 84 return element;
100 85 }
101 86
102 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 89 * insert element in tree
129 90 */
130 91 static
  92 +inline
131 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 102 static
  103 +inline
185 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 121 static
  122 +inline
360 123 void
361 124 segmentFree(struct memSegment * segment, int depth)
362 125 {
... ... @@ -378,8 +141,6 @@ TR_reference(void * mem)
378 141 return mem;
379 142 }
380 143
381   -pthread_mutex_t TR_memop_lock = PTHREAD_MUTEX_INITIALIZER;
382   -
383 144 /*
384 145 * This tries to reflect the memory management behaviour of the
385 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 171 void *
411 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 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 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 221 #endif
  222 + {
  223 + idx = -1;
  224 + }
445 225
446 226 if (NULL == seg) {
447   - seg = newElement(size);
  227 + seg = newElement(size, idx);
448 228 }
449 229
450 230 return seg->ptr;
... ... @@ -479,12 +259,15 @@ TR_free(void ** mem)
479 259 seg->ref_count--;
480 260 } else {
481 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 267 #endif
  268 + {
  269 + free(seg);
  270 + }
488 271 }
489 272
490 273 *mem = NULL;
... ... @@ -508,7 +291,15 @@ void
508 291 TR_cleanup()
509 292 {
510 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 303 #endif
513 304 }
514 305
... ...
Please register or login to post a comment