forked from enlightenment/efl
i'm playign with memory pools for evas lists. it seems to improve things.
SVN revision: 18612
This commit is contained in:
parent
d7aa8d7dc9
commit
4ae5471199
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -207,3 +207,437 @@ evas_debug_magic_string_get(DATA32 magic)
|
|||
};
|
||||
return "<UNKNOWN>";
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue