forked from enlightenment/efl
eina: minimize fragmentation of chainned mempool.
Summary: Previously: Each allocation happened in the first chain after any free. Now: All allocation will happen in one chain until all buckets are full, this can reduce fragmentation to some extent. Reviewers: seoz, govi, shilpasingh, raster, cedric Reviewed By: cedric Subscribers: cedric, rajeshps Differential Revision: https://phab.enlightenment.org/D2071 Signed-off-by: Cedric BAIL <cedric@osg.samsung.com>
This commit is contained in:
parent
0bd2fc15e9
commit
554b2cd9da
1
AUTHORS
1
AUTHORS
|
@ -50,6 +50,7 @@ Igor Murzov <e-mail@date.by>
|
|||
Vladislav Brovko <v.brovko@samsung.com>
|
||||
ChunEon Park (Hermet) <hermet@hermet.pe.kr>
|
||||
Rajeev Ranjan (Rajeev) <rajeev.r@samsung.com> <rajeev.jnnce@gmail.com>
|
||||
Subodh Kumar <s7158.kumar@samsung.com>
|
||||
|
||||
Eet
|
||||
---
|
||||
|
|
|
@ -68,26 +68,6 @@ static int _eina_chained_mp_log_dom = -1;
|
|||
static int aligned_chained_pool = 0;
|
||||
static int page_size = 0;
|
||||
|
||||
typedef struct _Chained_Mempool Chained_Mempool;
|
||||
struct _Chained_Mempool
|
||||
{
|
||||
Eina_Inlist *first;
|
||||
Eina_Rbtree *root;
|
||||
const char *name;
|
||||
int item_alloc;
|
||||
int pool_size;
|
||||
int alloc_size;
|
||||
int group_size;
|
||||
int usage;
|
||||
#ifdef EINA_DEBUG_MALLOC
|
||||
int minimal_size;
|
||||
#endif
|
||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||
Eina_Thread self;
|
||||
#endif
|
||||
Eina_Spinlock mutex;
|
||||
};
|
||||
|
||||
typedef struct _Chained_Pool Chained_Pool;
|
||||
struct _Chained_Pool
|
||||
{
|
||||
|
@ -100,6 +80,28 @@ struct _Chained_Pool
|
|||
unsigned char *limit;
|
||||
};
|
||||
|
||||
typedef struct _Chained_Mempool Chained_Mempool;
|
||||
struct _Chained_Mempool
|
||||
{
|
||||
Eina_Inlist *first;
|
||||
Eina_Rbtree *root;
|
||||
const char *name;
|
||||
int item_alloc;
|
||||
int pool_size;
|
||||
int alloc_size;
|
||||
int group_size;
|
||||
int usage;
|
||||
Chained_Pool* first_fill; //All allocation will happen in this chain,unless it is filled
|
||||
#ifdef EINA_DEBUG_MALLOC
|
||||
int minimal_size;
|
||||
#endif
|
||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||
Eina_Thread self;
|
||||
#endif
|
||||
Eina_Spinlock mutex;
|
||||
};
|
||||
|
||||
|
||||
static inline Eina_Rbtree_Direction
|
||||
_eina_chained_mp_pool_cmp(const Eina_Rbtree *left, const Eina_Rbtree *right, EINA_UNUSED void *data)
|
||||
{
|
||||
|
@ -244,6 +246,11 @@ _eina_chained_mempool_free_in(Chained_Mempool *pool, Chained_Pool *p, void *ptr)
|
|||
pool->first = eina_inlist_remove(pool->first, EINA_INLIST_GET(p));
|
||||
pool->root = eina_rbtree_inline_remove(pool->root, EINA_RBTREE_GET(p),
|
||||
_eina_chained_mp_pool_cmp, NULL);
|
||||
if (pool->first_fill == p)
|
||||
{
|
||||
pool->first_fill = NULL;
|
||||
pool->first_fill = EINA_INLIST_CONTAINER_GET(pool->first, Chained_Pool);
|
||||
}
|
||||
_eina_chained_mp_pool_free(p);
|
||||
|
||||
return EINA_TRUE;
|
||||
|
@ -271,12 +278,21 @@ eina_chained_mempool_malloc(void *data, EINA_UNUSED unsigned int size)
|
|||
#endif
|
||||
}
|
||||
|
||||
// Either we have some free space in the first one, or there is no free space.
|
||||
if (pool->first) p = EINA_INLIST_CONTAINER_GET(pool->first, Chained_Pool);
|
||||
//we have some free space in first fill chain
|
||||
if (pool->first_fill) p = pool->first_fill;
|
||||
|
||||
// base is not NULL - has a free slot
|
||||
if (p && !p->base && !p->last)
|
||||
{
|
||||
//Current pointed chain is filled , so point it to first one
|
||||
pool->first_fill = EINA_INLIST_CONTAINER_GET(pool->first, Chained_Pool);
|
||||
//Either first one has some free space or every chain is filled
|
||||
if (pool->first_fill && !pool->first_fill->base && !pool->first_fill->last)
|
||||
{
|
||||
p = NULL;
|
||||
pool->first_fill = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (p == NULL)
|
||||
|
@ -287,19 +303,20 @@ eina_chained_mempool_malloc(void *data, EINA_UNUSED unsigned int size)
|
|||
// we have reached the end of the list - no free pools
|
||||
if (!p)
|
||||
{
|
||||
p = _eina_chained_mp_pool_new(pool);
|
||||
if (!p)
|
||||
//new chain created ,point it to be the first_fill chain
|
||||
pool->first_fill = _eina_chained_mp_pool_new(pool);
|
||||
if (!pool->first_fill)
|
||||
{
|
||||
eina_spinlock_release(&pool->mutex);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pool->first = eina_inlist_prepend(pool->first, EINA_INLIST_GET(p));
|
||||
pool->root = eina_rbtree_inline_insert(pool->root, EINA_RBTREE_GET(p),
|
||||
pool->first = eina_inlist_prepend(pool->first, EINA_INLIST_GET(pool->first_fill));
|
||||
pool->root = eina_rbtree_inline_insert(pool->root, EINA_RBTREE_GET(pool->first_fill),
|
||||
_eina_chained_mp_pool_cmp, NULL);
|
||||
}
|
||||
|
||||
mem = _eina_chained_mempool_alloc_in(pool, p);
|
||||
mem = _eina_chained_mempool_alloc_in(pool, pool->first_fill);
|
||||
|
||||
eina_spinlock_release(&pool->mutex);
|
||||
|
||||
|
@ -487,7 +504,7 @@ eina_chained_mempool_init(const char *context,
|
|||
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||
mp->self = eina_thread_self();
|
||||
#endif
|
||||
|
||||
mp->first_fill = NULL;
|
||||
eina_spinlock_new(&mp->mutex);
|
||||
|
||||
return mp;
|
||||
|
|
Loading…
Reference in New Issue