From d34a0321cba607392ef07739322e963419bd5af5 Mon Sep 17 00:00:00 2001 From: Marcel Hollerbach Date: Fri, 31 Jul 2020 10:36:16 +0200 Subject: [PATCH] eo: make callback_add faster I was researching for quite some time how eo events could be made faster, while doing that i recognized that we are not utilizing the full size of Efl_Object_Data, so we can do a little bit more hinting for how our events are currently working. In this commit a flag called single priority is inserted. This flag ensures that the object only has one callback priority registered, which gives us the possibility of skipping the binary search, the search itself is not that bad, however, alone the loading of the instructions takes time, so this way we can skip the search, *and* the instructions for moving the array elements to later. Differential Revision: https://phab.enlightenment.org/D12078 --- src/lib/eo/eo_base_class.c | 55 +++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 19 deletions(-) diff --git a/src/lib/eo/eo_base_class.c b/src/lib/eo/eo_base_class.c index 565f4805e8..90aacaa459 100644 --- a/src/lib/eo/eo_base_class.c +++ b/src/lib/eo/eo_base_class.c @@ -90,6 +90,7 @@ struct _Efl_Object_Data Eina_Bool need_cleaning : 1; Eina_Bool allow_parent_unref : 1; // Allows unref to zero even with a parent + Eina_Bool single_priority : 1; }; typedef enum @@ -1477,19 +1478,9 @@ _eo_callback_search_sorted_near(const Efl_Object_Data *pd, const Eo_Callback_Des return middle; } -static void -_eo_callbacks_sorted_insert(Efl_Object_Data *pd, Eo_Callback_Description *cb) +static inline void +_eo_callbacks_array_bump(Efl_Object_Data *pd) { - Eo_Callback_Description **itr; - unsigned int length, j; - Efl_Event_Callback_Frame *frame; - - // Do a dichotomic searh - j = _eo_callback_search_sorted_near(pd, cb); - // Adjust for both case of length == 0 and when priority is equal. - while ((j < pd->callbacks_count) && - (pd->callbacks[j]->priority >= cb->priority)) j++; - // Increase the callbacks storage by 16 entries at a time if (_eo_nostep_alloc || (pd->callbacks_count & 0xF) == 0x0) { @@ -1503,14 +1494,38 @@ _eo_callbacks_sorted_insert(Efl_Object_Data *pd, Eo_Callback_Description *cb) if (EINA_UNLIKELY(!tmp)) return; pd->callbacks = tmp; } +} - // FIXME: Potential improvement, merge single callback description of the same priority - // into an array when possible - itr = pd->callbacks + j; - length = pd->callbacks_count - j; - if (length > 0) memmove(itr + 1, itr, - length * sizeof(Eo_Callback_Description *)); - *itr = cb; +static void +_eo_callbacks_sorted_insert(Efl_Object_Data *pd, Eo_Callback_Description *cb) +{ + Eo_Callback_Description **itr; + unsigned int length, j; + Efl_Event_Callback_Frame *frame; + + if (pd->single_priority && cb->priority == 0) + { + _eo_callbacks_array_bump(pd); + pd->callbacks[pd->callbacks_count] = cb; + } + else + { + pd->single_priority = EINA_FALSE; + // Do a dichotomic searh + j = _eo_callback_search_sorted_near(pd, cb); + // Adjust for both case of length == 0 and when priority is equal. + while ((j < pd->callbacks_count) && + (pd->callbacks[j]->priority >= cb->priority)) j++; + _eo_callbacks_array_bump(pd); + // FIXME: Potential improvement, merge single callback description of the same priority + // into an array when possible + itr = pd->callbacks + j; + length = pd->callbacks_count - j; + if (length > 0) memmove(itr + 1, itr, + length * sizeof(Eo_Callback_Description *)); + *itr = cb; + + } pd->callbacks_count++; @@ -2680,6 +2695,8 @@ _efl_object_constructor(Eo *obj, Efl_Object_Data *pd EINA_UNUSED) { DBG("%p - %s.", obj, efl_class_name_get(obj)); + pd->single_priority = EINA_TRUE; + _eo_condtor_done(obj); return obj;