From 4ae547119941cc9939ea81d7b11b59abc5b99234 Mon Sep 17 00:00:00 2001 From: Carsten Haitzler Date: Wed, 23 Nov 2005 10:43:54 +0000 Subject: [PATCH] i'm playign with memory pools for evas lists. it seems to improve things. SVN revision: 18612 --- legacy/evas/src/lib/data/evas_list.c | 40 +- legacy/evas/src/lib/include/evas_private.h | 14 + legacy/evas/src/lib/main.c | 434 +++++++++++++++++++++ 3 files changed, 475 insertions(+), 13 deletions(-) diff --git a/legacy/evas/src/lib/data/evas_list.c b/legacy/evas/src/lib/data/evas_list.c index d93f86155e..f9d9b4030f 100644 --- a/legacy/evas/src/lib/data/evas_list.c +++ b/legacy/evas/src/lib/data/evas_list.c @@ -14,6 +14,20 @@ struct _Evas_List_Accounting static int _evas_list_alloc_error = 0; +static Evas_Mempool _evas_list_mempool = +{ + sizeof(Evas_List), + (4096 - (34 * sizeof(int)) - (sizeof(void *) * 2)) / sizeof(Evas_List), +// 32, + 0, NULL +}; +static Evas_Mempool _evas_list_accounting_mempool = +{ + sizeof(Evas_List_Accounting), + 32, + 0, NULL +}; + /** * @defgroup Evas_List_Data_Group Linked List Creation Functions * @@ -52,7 +66,7 @@ evas_list_append(Evas_List *list, const void *data) Evas_List *l, *new_l; _evas_list_alloc_error = 0; - new_l = malloc(sizeof(Evas_List)); + new_l = evas_mempool_malloc(&_evas_list_mempool, sizeof(Evas_List)); if (!new_l) { _evas_list_alloc_error = 1; @@ -63,11 +77,11 @@ evas_list_append(Evas_List *list, const void *data) if (!list) { new_l->prev = NULL; - new_l->accounting = malloc(sizeof(Evas_List_Accounting)); + new_l->accounting = evas_mempool_malloc(&_evas_list_accounting_mempool, sizeof(Evas_List_Accounting)); if (!new_l->accounting) { _evas_list_alloc_error = 1; - free(new_l); + evas_mempool_free(&_evas_list_mempool, new_l); return list; } ((Evas_List_Accounting *)(new_l->accounting))->last = new_l; @@ -115,7 +129,7 @@ evas_list_prepend(Evas_List *list, const void *data) Evas_List *new_l; _evas_list_alloc_error = 0; - new_l = malloc(sizeof(Evas_List)); + new_l = evas_mempool_malloc(&_evas_list_mempool, sizeof(Evas_List)); if (!new_l) { _evas_list_alloc_error = 1; @@ -126,11 +140,11 @@ evas_list_prepend(Evas_List *list, const void *data) if (!list) { new_l->next = NULL; - new_l->accounting = malloc(sizeof(Evas_List_Accounting)); + new_l->accounting = evas_mempool_malloc(&_evas_list_accounting_mempool, sizeof(Evas_List_Accounting)); if (!new_l->accounting) { _evas_list_alloc_error = 1; - free(new_l); + evas_mempool_free(&_evas_list_mempool, new_l); return list; } ((Evas_List_Accounting *)(new_l->accounting))->last = new_l; @@ -193,7 +207,7 @@ evas_list_append_relative(Evas_List *list, const void *data, const void *relativ { Evas_List *new_l; - new_l = malloc(sizeof(Evas_List)); + new_l = evas_mempool_malloc(&_evas_list_mempool, sizeof(Evas_List)); if (!new_l) { _evas_list_alloc_error = 1; @@ -276,7 +290,7 @@ evas_list_prepend_relative(Evas_List *list, const void *data, const void *relati { Evas_List *new_l; - new_l = malloc(sizeof(Evas_List)); + new_l = evas_mempool_malloc(&_evas_list_mempool, sizeof(Evas_List)); if (!new_l) { _evas_list_alloc_error = 1; @@ -375,8 +389,8 @@ evas_list_remove_list(Evas_List *list, Evas_List *remove_list) ((Evas_List_Accounting *)(list->accounting))->last = remove_list->prev; ((Evas_List_Accounting *)(list->accounting))->count--; if (((Evas_List_Accounting *)(list->accounting))->count == 0) - free(list->accounting); - free(remove_list); + evas_mempool_free(&_evas_list_accounting_mempool, list->accounting); + evas_mempool_free(&_evas_list_mempool, remove_list); return return_l; } @@ -478,12 +492,12 @@ evas_list_free(Evas_List *list) Evas_List *l, *free_l; if (!list) return NULL; - free(list->accounting); + evas_mempool_free(&_evas_list_accounting_mempool, list->accounting); for (l = list; l;) { free_l = l; l = l->next; - free(free_l); + evas_mempool_free(&_evas_list_mempool, free_l); } return NULL; } @@ -892,7 +906,7 @@ evas_list_sort(Evas_List *list, int size, int (*func)(void *, void *)) ll->prev->next = NULL; ll->prev = NULL; } - ll->accounting = malloc(sizeof(Evas_List_Accounting)); + ll->accounting = evas_mempool_malloc(&_evas_list_accounting_mempool, sizeof(Evas_List_Accounting)); ((Evas_List_Accounting *)(ll->accounting))->last = llast; ((Evas_List_Accounting *)(ll->accounting))->count = size - mid; diff --git a/legacy/evas/src/lib/include/evas_private.h b/legacy/evas/src/lib/include/evas_private.h index e3eff0b1ce..f5ca65cec4 100644 --- a/legacy/evas/src/lib/include/evas_private.h +++ b/legacy/evas/src/lib/include/evas_private.h @@ -618,6 +618,20 @@ struct _Evas_Imaging_Font RGBA_Font *font; }; +typedef struct _Evas_Mempool Evas_Mempool; + +struct _Evas_Mempool +{ + int item_size; + int pool_size; + int usage; + void *first; +}; + +void *evas_mempool_malloc(Evas_Mempool *pool, int size); +void evas_mempool_free(Evas_Mempool *pool, void *ptr); +void *evas_mempool_calloc(Evas_Mempool *pool, int size); + #ifdef __cplusplus } #endif diff --git a/legacy/evas/src/lib/main.c b/legacy/evas/src/lib/main.c index fce3bcb286..ac647f6fb9 100644 --- a/legacy/evas/src/lib/main.c +++ b/legacy/evas/src/lib/main.c @@ -207,3 +207,437 @@ evas_debug_magic_string_get(DATA32 magic) }; return ""; } + +typedef struct _Evas_Mempool1 Evas_Mempool1; +typedef struct _Evas_Mempool2 Evas_Mempool2; +typedef unsigned int Evas_Mempool_Bitmask; + +struct _Evas_Mempool1 /* used if pool size <= 32 */ +{ + Evas_Mempool_Bitmask allocated; + Evas_Mempool1 *next; + unsigned char *mem; +}; + +struct _Evas_Mempool2 /* used if pool size > 32 */ +{ + Evas_Mempool_Bitmask allocated, filled; + Evas_Mempool_Bitmask allocated_list[32]; + Evas_Mempool2 *next; + unsigned char *mem; +}; + +static Evas_Mempool1 * +_evas_mempoool1_new(Evas_Mempool *pool) +{ + Evas_Mempool1 *mp; + + if (pool->pool_size <= 32) + mp = malloc(sizeof(Evas_Mempool1) + (pool->item_size * pool->pool_size)); + else + mp = malloc(sizeof(Evas_Mempool1) + (pool->item_size * 32)); + mp->allocated = 0; + mp->next = NULL; + mp->mem = (unsigned char *)mp + sizeof(Evas_Mempool1); + return mp; +} + +static void +_evas_mempool1_free(Evas_Mempool1 *mp) +{ + free(mp); +} + +static Evas_Mempool1 * +_evas_mempool1_free_find(Evas_Mempool *pool, int *slot, Evas_Mempool1 **pmp) +{ + Evas_Mempool1 *mp; + int i, psize; + Evas_Mempool_Bitmask allocated; + + psize = pool->pool_size; + if (psize > 32) psize = 32; + for (mp = (Evas_Mempool1 *)pool->first; mp; mp = mp->next) + { + allocated = mp->allocated; + if (allocated != 0xffffffff) + { + for (i = 0; i < psize; i++) + { + if ((allocated & (1 << i)) == 0) + { + *slot = i; + return mp; + } + } + } + *pmp = mp; + if (!mp->next) mp->next = _evas_mempoool1_new(pool); + } + return NULL; +} + +static Evas_Mempool1 * +_evas_mempool1_pointer_find(Evas_Mempool *pool, int *slot, Evas_Mempool1 **pmp, unsigned char *ptr) +{ + Evas_Mempool1 *mp; + int i, psize, isize; + unsigned char *mem; + + psize = pool->pool_size; + if (psize > 32) psize = 32; + isize = pool->item_size; + for (mp = (Evas_Mempool1 *)pool->first; mp; mp = mp->next) + { + mem = mp->mem; + if (ptr >= mem) + { + i = (ptr - mem) / isize; + if (i < psize) + { + *slot = i; + return mp; + } + } + *pmp = mp; + } + return NULL; +} + +static void +_evas_mempool1_slot_set(Evas_Mempool1 *mp, int slot) +{ + mp->allocated |= (1 << slot); +} + +static void +_evas_mempool1_slot_unset(Evas_Mempool1 *mp, int slot) +{ + mp->allocated &= ~(1 << slot); +} + +/* +static void +_evas_mempool1_debug(Evas_Mempool *pool) +{ + Evas_Mempool1 *mp; + int psize, isize, i, j, bits, space, allocated, nodes; + + psize = pool->pool_size; + if (psize > 32) psize = 32; + isize = pool->item_size; + nodes = allocated = space = 0; + for (i = 0, mp = (Evas_Mempool1 *)pool->first; mp; mp = mp->next, i++) + { + bits = 0; + + for (j = 0; j < 32; j++) + { + if ((mp->allocated & (1 << j)) != 0) bits++; + } + allocated += bits * isize; + space += psize * isize; + nodes++; +// printf("pool %i, alloc %08x, full %i/%i\n", +// i, mp->allocated, bits, 32); + } + printf("pool[0-32] %p usage (%i @ %i, %i nodes) %3.1f%%\n", + pool, pool->usage, psize, nodes, + 100.0 * (double)allocated / (double)space); +} +*/ + + + +static Evas_Mempool2 * +_evas_mempoool2_new(Evas_Mempool *pool) +{ + Evas_Mempool2 *mp; + + if (pool->pool_size <= 1024) + mp = malloc(sizeof(Evas_Mempool2) + (pool->item_size * pool->pool_size)); + else + mp = malloc(sizeof(Evas_Mempool2) + (pool->item_size * 1024)); + mp->allocated = 0; + mp->filled = 0; + memset(mp->allocated_list, 0, sizeof(int) * 32); + mp->next = NULL; + mp->mem = (unsigned char *)mp + sizeof(Evas_Mempool2); + return mp; +} + +static void +_evas_mempool2_free(Evas_Mempool2 *mp) +{ + free(mp); +} + +static Evas_Mempool2 * +_evas_mempool2_free_find(Evas_Mempool *pool, int *slot, Evas_Mempool2 **pmp) +{ + Evas_Mempool2 *mp; + int i, j, psize, ps, bsize; + Evas_Mempool_Bitmask allocated, filled; + + psize = pool->pool_size; + if (psize > 1024) psize = 1024; + bsize = (psize + 31) / 32; + for (mp = (Evas_Mempool2 *)pool->first; mp; mp = mp->next) + { + filled = mp->filled; + if (filled != 0xffffffff) + { + for (j = 0; j < bsize; j++) + { + if ((filled & (1 << j)) == 0) + { + if (j == bsize - 1) + ps = psize - (j * 32); + else + ps = 32; + allocated = mp->allocated_list[j]; + for (i = 0; i < ps; i++) + { + if ((allocated & (1 << i)) == 0) + { + *slot = (j * 32) + i; + return mp; + } + } + } + } + } + *pmp = mp; + if (!mp->next) mp->next = _evas_mempoool2_new(pool); + } + return NULL; +} + +static Evas_Mempool2 * +_evas_mempool2_pointer_find(Evas_Mempool *pool, int *slot, Evas_Mempool2 **pmp, unsigned char *ptr) +{ + Evas_Mempool2 *mp; + int i, psize, isize; + unsigned char *mem; + + psize = pool->pool_size; + if (psize > 1024) psize = 1024; + isize = pool->item_size; + for (mp = (Evas_Mempool2 *)pool->first; mp; mp = mp->next) + { + mem = mp->mem; + if (ptr >= mem) + { + i = (ptr - mem) / isize; + if (i < psize) + { + *slot = i; + return mp; + } + } + *pmp = mp; + } + return NULL; +} + +static void +_evas_mempool2_slot_set(Evas_Mempool2 *mp, int slot) +{ + int bucket; + + bucket = slot / 32; + mp->allocated_list[bucket] |= (1 << (slot - (bucket * 32))); + mp->allocated |= (1 << bucket); + if (mp->allocated_list[bucket] == 0xffffffff) + mp->filled |= (1 << bucket); +} + +static void +_evas_mempool2_slot_unset(Evas_Mempool2 *mp, int slot) +{ + int bucket; + + bucket = slot / 32; + mp->allocated_list[bucket] &= ~(1 << (slot - (bucket * 32))); + mp->filled &= ~(1 << bucket); + if (mp->allocated_list[bucket] == 0) + mp->allocated &= ~(1 << bucket); +} + +/* +static void +_evas_mempool2_debug(Evas_Mempool *pool) +{ + Evas_Mempool2 *mp; + int psize, bsize, isize, i, j, ps, bits, allocated, space, nodes; + + psize = pool->pool_size; + if (psize > 1024) psize = 1024; + bsize = (psize + 31) / 32; + isize = pool->item_size; + nodes = allocated = space = 0; + for (i = 0, mp = (Evas_Mempool2 *)pool->first; mp; mp = mp->next, i++) + { + for (i = 0; i < bsize; i++) + { + bits = 0; + if (i == bsize - 1) + ps = psize - (i * 32); + else + ps = 32; + for (j = 0; j < ps; j++) + { + if ((mp->allocated_list[i] & (1 << j)) != 0) bits++; + } +// printf("pool %i, alloc %08x, full %i/%i\n", +// i, mp->allocated, bits, 32); + allocated += bits * isize; + } + space += psize * isize; + nodes++; + } + printf("pool[32-1024] %p usage (%i @ %i, %i nodes) %3.1f%%\n", + pool, pool->usage, psize, nodes, + 100.0 * (double)allocated / (double)space); +} +*/ + +/*#define NOPOOL 1*/ + +void * +evas_mempool_malloc(Evas_Mempool *pool, int size) +#ifdef NOPOOL +{ + return malloc(size); +} +#else +{ + if (pool->pool_size <= 32) + { + Evas_Mempool1 *mp, *pmp = NULL; + int freeslot; + + mp = pool->first; + if (!mp) + { + mp = _evas_mempoool1_new(pool); + pool->first = mp; + freeslot = 0; + } + else mp = _evas_mempool1_free_find(pool, &freeslot, &pmp); + if (!mp) return NULL; + pool->usage++; + _evas_mempool1_slot_set(mp, freeslot); + if (mp->allocated == 0xffffffff) + { + if (mp->next) + { + if (pool->first == mp) pool->first = mp->next; + else pmp->next = mp; + mp->next = NULL; + } + } +/* _evas_mempool1_debug(pool);*/ + return mp->mem + (freeslot * pool->item_size); + } + else + { + Evas_Mempool2 *mp, *pmp = NULL; + int freeslot; + + mp = pool->first; + if (!mp) + { + mp = _evas_mempoool2_new(pool); + pool->first = mp; + freeslot = 0; + } + else mp = _evas_mempool2_free_find(pool, &freeslot, &pmp); + if (!mp) return NULL; + pool->usage++; + _evas_mempool2_slot_set(mp, freeslot); + if (mp->allocated == 0xffffffff) + { + if (mp->next) + { + if (pool->first == mp) pool->first = mp->next; + else pmp->next = mp; + mp->next = NULL; + } + } +/* _evas_mempool2_debug(pool);*/ + return mp->mem + (freeslot * pool->item_size); + } +} +#endif + +void +evas_mempool_free(Evas_Mempool *pool, void *ptr) +#ifdef NOPOOL +{ + free(ptr); +} +#else +{ + if (pool->pool_size <= 32) + { + Evas_Mempool1 *mp, *pmp = NULL; + int allocslot; + + mp = _evas_mempool1_pointer_find(pool, &allocslot, &pmp, (unsigned char*)ptr); + if (!mp) return; + _evas_mempool1_slot_unset(mp, allocslot); + if (mp->allocated == 0) + { + if (pool->first == mp) pool->first = mp->next; + else pmp->next = mp->next; + _evas_mempool1_free(mp); + } + else + { + if (pool->first != mp) + { + pmp->next = mp->next; + mp->next = pool->first; + pool->first = mp; + } + } + pool->usage--; + } + else + { + Evas_Mempool2 *mp, *pmp = NULL; + int allocslot; + + mp = _evas_mempool2_pointer_find(pool, &allocslot, &pmp, (unsigned char*)ptr); + if (!mp) return; + _evas_mempool2_slot_unset(mp, allocslot); + if (mp->allocated == 0) + { + if (pool->first == mp) pool->first = mp->next; + else pmp->next = mp->next; + _evas_mempool2_free(mp); + } + else + { + if (pool->first != mp) + { + pmp->next = mp->next; + mp->next = pool->first; + pool->first = mp; + } + } + pool->usage--; + } +} +#endif + +void * +evas_mempool_calloc(Evas_Mempool *pool, int size) +{ + void *mem; + + mem = evas_mempool_malloc(pool, size); + memset(mem, 0, size); + return mem; +}