eo: prevent unecessary callback call walk.
authorCedric Bail <cedric.bail@free.fr>
Wed, 16 Oct 2019 00:04:32 +0000 (17:04 -0700)
committerWonki Kim <wonki_.kim@samsung.com>
Mon, 11 Nov 2019 02:20:41 +0000 (11:20 +0900)
This patch introduce a small hash (64 or 32bits) that cache all existing
Efl_Event_Description callback handler registered on an object. It slightly
reduce the time needed to do an unecessary call and cost just a few bytes
per object.

Reviewed-by: Marcel Hollerbach <mail@marcel-hollerbach.de>
Differential Revision: https://phab.enlightenment.org/D10475

src/lib/eo/eo_base_class.c
src/tests/eo/suite/eo_test_general.c

index 67deec8..b3cd4a6 100644 (file)
@@ -53,6 +53,11 @@ struct _Efl_Object_Data
 
    Efl_Event_Callback_Frame  *event_frame;
    Eo_Callback_Description  **callbacks;
+#ifdef EFL64
+   uint64_t                   callbacks_mask;
+#else
+   uint32_t                   callbacks_mask;
+#endif
    Eina_Inlist               *pending_futures;
    unsigned int               callbacks_count;
 
@@ -1209,9 +1214,26 @@ _efl_pending_future_new(void)
 #define CB_COUNT_INC(cnt) do { if ((cnt) != 0xffff) (cnt)++; } while(0)
 #define CB_COUNT_DEC(cnt) do { if ((cnt) != 0xffff) (cnt)--; } while(0)
 
+static inline unsigned char
+_pointer_hash(const uintptr_t val)
+{
+   static const unsigned char shift = (unsigned char) log2(1 + sizeof (Efl_Event_Description));
+#ifdef EFL64
+   return (unsigned char)(((val) >> shift) & 0x3F);
+#else
+   return (unsigned char)(((val) >> shift) & 0x1F);
+#endif
+}
+
 static inline void
 _special_event_count_inc(Eo *obj_id, Efl_Object_Data *pd, const Efl_Callback_Array_Item *it)
 {
+   int event_hash;
+
+   event_hash = _pointer_hash((uintptr_t) it->desc);
+
+   pd->callbacks_mask |= 1 << event_hash;
+
    if      (it->desc == EFL_EVENT_CALLBACK_ADD)
      CB_COUNT_INC(pd->event_cb_efl_event_callback_add_count);
    else if (it->desc == EFL_EVENT_CALLBACK_DEL)
@@ -1682,6 +1704,7 @@ _event_callback_call(Eo *obj_id, Efl_Object_Data *pd,
       .inserted_before = 0,
       .generation = 1,
    };
+   int event_hash;
 
    if (pd->callbacks_count == 0) return EINA_FALSE;
    else if ((desc == EFL_EVENT_CALLBACK_ADD) &&
@@ -1695,6 +1718,13 @@ _event_callback_call(Eo *obj_id, Efl_Object_Data *pd,
    else if ((desc == EFL_EVENT_NOREF) &&
             (pd->event_cb_efl_event_noref_count == 0)) return EINA_FALSE;
 
+   if (!legacy_compare)
+     {
+        event_hash = _pointer_hash((uintptr_t) desc);
+        if (!(pd->callbacks_mask & (1 << event_hash)))
+          return EINA_FALSE;
+     }
+
    if (pd->event_frame)
      frame.generation = ((Efl_Event_Callback_Frame*)pd->event_frame)->generation + 1;
 
index 1494f46..61bf10b 100644 (file)
@@ -1808,9 +1808,9 @@ EFL_START_TEST(efl_object_size)
    // Update this number only if you modified the class size on purpose
 
 #ifdef EO_DEBUG
-   ck_assert_int_le(efl_class_memory_size_get(SIMPLE_CLASS), 164);
+   ck_assert_int_le(efl_class_memory_size_get(SIMPLE_CLASS), 180);
 #else
-   ck_assert_int_le(efl_class_memory_size_get(SIMPLE_CLASS), 148);
+   ck_assert_int_le(efl_class_memory_size_get(SIMPLE_CLASS), 164);
 #endif
 }
 EFL_END_TEST