From b4456121be0c964a88451e20a42fea2059a61a21 Mon Sep 17 00:00:00 2001 From: Cedric Bail Date: Fri, 22 Apr 2016 10:58:25 -0700 Subject: [PATCH] eina: implement a memory cache for Eina_Rbtree_Iterator. So it seems we are using Eina_Hash_Iterator quite a lot more than before. This lead to a huge amount of alloc/free of Eina_Rbtree_Iterator that was noticable in Enlightenment callgrind trace. This patch make it vanish from the trace :-) --- src/lib/eina/eina_main.c | 4 ++- src/lib/eina/eina_rbtree.c | 67 +++++++++++++++++++++++++++++++++++++--------- 2 files changed, 57 insertions(+), 14 deletions(-) diff --git a/src/lib/eina/eina_main.c b/src/lib/eina/eina_main.c index ffb0177..8c084db 100644 --- a/src/lib/eina/eina_main.c +++ b/src/lib/eina/eina_main.c @@ -153,6 +153,7 @@ EAPI Eina_Inlist *_eina_tracking = NULL; S(cow); S(cpu); S(thread_queue); + S(rbtree); /* no model for now S(model); */ @@ -198,7 +199,8 @@ static const struct eina_desc_setup _eina_desc_setup[] = { S(thread), S(cow), S(cpu), - S(thread_queue) + S(thread_queue), + S(rbtree) /* no model for now S(model) */ diff --git a/src/lib/eina/eina_rbtree.c b/src/lib/eina/eina_rbtree.c index 61de138..ab2a001 100644 --- a/src/lib/eina/eina_rbtree.c +++ b/src/lib/eina/eina_rbtree.c @@ -30,6 +30,7 @@ #include "eina_private.h" #include "eina_array.h" #include "eina_trash.h" +#include "eina_lock.h" /* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ #include "eina_safety_checks.h" @@ -64,6 +65,9 @@ struct _Eina_Iterator_Rbtree_List Eina_Bool up : 1; }; +static Eina_Array iterator_trash; +static Eina_Spinlock iterator_trash_lock; + static Eina_Iterator_Rbtree_List * _eina_rbtree_iterator_list_new(Eina_Iterator_Rbtree *it, const Eina_Rbtree *tree) { @@ -93,7 +97,7 @@ _eina_rbtree_iterator_get_content(Eina_Iterator_Rbtree *it) } static void -_eina_rbtree_iterator_free(Eina_Iterator_Rbtree *it) +_eina_rbtree_iterator_forced_free(Eina_Iterator_Rbtree *it) { Eina_Iterator_Rbtree_List *item; Eina_Array_Iterator et; @@ -109,6 +113,22 @@ _eina_rbtree_iterator_free(Eina_Iterator_Rbtree *it) free(it); } +static void +_eina_rbtree_iterator_free(Eina_Iterator_Rbtree *it) +{ + if (eina_array_count(&iterator_trash) >= 7) + { + _eina_rbtree_iterator_forced_free(it); + return ; + } + + eina_array_flush(it->stack); + + eina_spinlock_take(&iterator_trash_lock); + eina_array_push(&iterator_trash, it); + eina_spinlock_release(&iterator_trash_lock); +} + static Eina_Bool _eina_rbtree_iterator_next(Eina_Iterator_Rbtree *it, void **data) { @@ -190,18 +210,23 @@ _eina_rbtree_iterator_build(const Eina_Rbtree *root, unsigned char mask) Eina_Iterator_Rbtree_List *first; Eina_Iterator_Rbtree *it; - it = calloc(1, sizeof (Eina_Iterator_Rbtree)); - if (!it) return NULL; + eina_spinlock_take(&iterator_trash_lock); + it = eina_array_pop(&iterator_trash); + eina_spinlock_release(&iterator_trash_lock); + + if (!it) + { + it = calloc(1, sizeof (Eina_Iterator_Rbtree)); + if (!it) return NULL; - eina_trash_init(&it->trash); + eina_trash_init(&it->trash); - it->stack = eina_array_new(8); - if (!it->stack) - goto on_error2; + it->stack = eina_array_new(8); + if (!it->stack) goto on_error; + } first = _eina_rbtree_iterator_list_new(it, root); - if (!first) - goto on_error; + if (!first) goto on_error; eina_array_push(it->stack, first); @@ -218,10 +243,7 @@ _eina_rbtree_iterator_build(const Eina_Rbtree *root, unsigned char mask) return &it->iterator; on_error: - eina_array_free(it->stack); -on_error2: - free(it); - + _eina_rbtree_iterator_free(it); return NULL; } @@ -512,3 +534,22 @@ eina_rbtree_delete(Eina_Rbtree *root, Eina_Rbtree_Free_Cb func, void *data) eina_rbtree_delete(root->son[1], func, data); func(root, data); } + +Eina_Bool +eina_rbtree_init(void) +{ + eina_array_step_set(&iterator_trash, sizeof(iterator_trash), 8); + return eina_spinlock_new(&iterator_trash_lock); +} + +Eina_Bool +eina_rbtree_shutdown(void) +{ + Eina_Iterator_Rbtree *it; + + while ((it = eina_array_pop(&iterator_trash))) + _eina_rbtree_iterator_forced_free(it); + eina_array_flush(&iterator_trash); + eina_spinlock_free(&iterator_trash_lock); + return EINA_TRUE; +} -- 2.7.4