eo: do not call eina_tls_get as often when in the main loop.
authorCedric BAIL <cedric@osg.samsung.com>
Fri, 1 Aug 2014 10:21:40 +0000 (12:21 +0200)
committerCedric BAIL <cedric@osg.samsung.com>
Thu, 4 Sep 2014 16:11:45 +0000 (18:11 +0200)
eina_tls_get is really slow, having a fast path for the main loop does really
help us right now. It is also unlikely that slowing down a little bit the use
of eo in thread is going to have any impact on application speed any time soon.

I win a +10% on expedite benchmark compared to without.

Signed-off-by: Cedric BAIL <cedric@osg.samsung.com>
src/lib/eo/Eo.h
src/lib/eo/eo.c

index 30ae45e..14e85f1 100644 (file)
@@ -493,12 +493,13 @@ EAPI extern Eo_Hook_Call eo_hook_call_post;
        Hook(call.klass, call.obj, call.func, __VA_ARGS__);
 
 // cache OP id, get real fct and object data then do the call
-#define EO_FUNC_COMMON_OP(Name, DefRet)                                \
-     Eo_Op_Call_Data call;                                             \
+#define EO_FUNC_COMMON_OP(Name, DefRet)                                 \
+     Eo_Op_Call_Data call;                                              \
+     Eina_Bool is_main_loop = eina_main_loop_is();                      \
      static Eo_Op op = EO_NOOP;                                         \
      if (op == EO_NOOP)                                                 \
-        op = _eo_api_op_id_get((void*) Name, __FILE__, __LINE__);      \
-     if (!_eo_call_resolve(#Name, op, &call, __FILE__, __LINE__)) return DefRet; \
+       op = _eo_api_op_id_get((void*) Name, is_main_loop, __FILE__, __LINE__); \
+     if (!_eo_call_resolve(#Name, op, &call, is_main_loop, __FILE__, __LINE__)) return DefRet; \
      _Eo_##Name##_func _func_ = (_Eo_##Name##_func) call.func;        \
 
 // to define an EAPI function
@@ -566,13 +567,13 @@ EAPI extern Eo_Hook_Call eo_hook_call_post;
 #define EO_OP_SENTINEL { _EO_OP_API_ENTRY(NULL), NULL, 0, EO_OP_TYPE_INVALID, NULL }
 
 // returns the OP id corresponding to the given api_func
-EAPI Eo_Op _eo_api_op_id_get(const void *api_func, const char *file, int line);
+EAPI Eo_Op _eo_api_op_id_get(const void *api_func, Eina_Bool is_main_loop, const char *file, int line);
 
 // gets the real function pointer and the object data
-EAPI Eina_Bool _eo_call_resolve(const char *func_name, const Eo_Op op, Eo_Op_Call_Data *call, const char *file, int line);
+EAPI Eina_Bool _eo_call_resolve(const char *func_name, const Eo_Op op, Eo_Op_Call_Data *call, Eina_Bool is_main_loop, const char *file, int line);
 
 // start of eo_do barrier, gets the object pointer and ref it, put it on the stask
-EAPI Eina_Bool _eo_do_start(const Eo *obj, const Eo_Class *cur_klass, Eina_Bool is_super, const char *file, const char *func, int line);
+  EAPI Eina_Bool _eo_do_start(const Eo *obj, const Eo_Class *cur_klass, Eina_Bool is_super, Eina_Bool is_main_loop, const char *file, const char *func, int line);
 
 // end of the eo_do barrier, unref the obj, move the stack pointer
 EAPI void _eo_do_end(const Eo **ojb);
@@ -581,11 +582,12 @@ EAPI void _eo_do_end(const Eo **ojb);
 
 // eo object method calls batch,
 
-#define _eo_do_common(eoid, clsid, is_super, ...)                         \
-    ({                                                                      \
-       const Eo *_eoid_ EO_DO_CLEANUP = eoid;                             \
-       _eo_do_start(_eoid_, clsid, is_super, __FILE__, __FUNCTION__, __LINE__);  \
-       __VA_ARGS__;                                                   \
+#define _eo_do_common(eoid, clsid, is_super, ...)                       \
+  ({                                                                    \
+       Eina_Bool is_main_loop = eina_main_loop_is();                    \
+       const Eo *_eoid_ EO_DO_CLEANUP = eoid;                           \
+       _eo_do_start(_eoid_, clsid, is_super, is_main_loop, __FILE__, __FUNCTION__, __LINE__); \
+       __VA_ARGS__;                                                     \
     })
 
 
index 261c2a9..b5df088 100644 (file)
@@ -390,9 +390,11 @@ _eo_call_stack_free(void *ptr)
 }
 
 static inline Eo_Call_Stack *
-_eo_call_stack_get()
+_eo_call_stack_get(Eina_Bool is_main_loop)
 {
-   Eo_Call_Stack *stack = eina_tls_get(_eo_call_stack_key);
+   static Eo_Call_Stack *main_loop_stack = NULL;
+   Eo_Call_Stack *stack = is_main_loop ?
+     main_loop_stack : eina_tls_get(_eo_call_stack_key);
 
    if (stack) return stack;
 
@@ -403,7 +405,11 @@ _eo_call_stack_get()
         return NULL;
      }
 
-   if (!eina_tls_set(_eo_call_stack_key, stack))
+   if (is_main_loop)
+     {
+        main_loop_stack = stack;
+     }
+   else if (!eina_tls_set(_eo_call_stack_key, stack))
      {
         EINA_LOG_ERR("Could not set eo call stack in TLS key.");
         _eo_call_stack_free(stack);
@@ -511,11 +517,11 @@ _eo_do_internal(const Eo *eo_id, const Eo_Class *cur_klass_id,
 }
 
 EAPI Eina_Bool
-_eo_do_start(const Eo *eo_id, const Eo_Class *cur_klass_id, Eina_Bool is_super, const char *file EINA_UNUSED, const char *func EINA_UNUSED, int line EINA_UNUSED)
+_eo_do_start(const Eo *eo_id, const Eo_Class *cur_klass_id, Eina_Bool is_super, Eina_Bool is_main_loop, const char *file EINA_UNUSED, const char *func EINA_UNUSED, int line EINA_UNUSED)
 {
    Eina_Bool ret = EINA_TRUE;
    Eo_Stack_Frame *fptr, *pfptr;
-   Eo_Call_Stack *stack = _eo_call_stack_get();
+   Eo_Call_Stack *stack = _eo_call_stack_get(is_main_loop);
 
    if (stack->frame_ptr == stack->last_frame)
      _eo_call_stack_resize(stack, EINA_TRUE);
@@ -542,7 +548,7 @@ EAPI void
 _eo_do_end(const Eo **eo_id EINA_UNUSED)
 {
    Eo_Stack_Frame *fptr;
-   Eo_Call_Stack *stack = _eo_call_stack_get();
+   Eo_Call_Stack *stack = _eo_call_stack_get(eina_main_loop_is()); // Is it possible to extract information from the scope ?
 
    fptr = stack->frame_ptr;
 
@@ -564,7 +570,7 @@ _eo_do_end(const Eo **eo_id EINA_UNUSED)
 }
 
 EAPI Eina_Bool
-_eo_call_resolve(const char *func_name, const Eo_Op op, Eo_Op_Call_Data *call, const char *file, int line)
+  _eo_call_resolve(const char *func_name, const Eo_Op op, Eo_Op_Call_Data *call, Eina_Bool is_main_loop, const char *file, int line)
 {
    Eo_Stack_Frame *fptr;
    const _Eo_Class *klass;
@@ -573,7 +579,7 @@ _eo_call_resolve(const char *func_name, const Eo_Op op, Eo_Op_Call_Data *call, c
 
    if (op == EO_NOOP) return EINA_FALSE;
 
-   fptr = _eo_call_stack_get()->frame_ptr;
+   fptr = _eo_call_stack_get(is_main_loop)->frame_ptr;
 
    if (EINA_UNLIKELY(!fptr->o.obj))
       return EINA_FALSE;
@@ -755,11 +761,11 @@ _eo_api_desc_get(const void *api_func, const _Eo_Class *klass, const _Eo_Class *
 }
 
 EAPI Eo_Op
-_eo_api_op_id_get(const void *api_func, const char *file, int line)
+_eo_api_op_id_get(const void *api_func, Eina_Bool is_main_loop, const char *file, int line)
 {
    const Eo_Op_Description *desc;
    const _Eo_Class *klass;
-   Eo_Call_Stack *stack = _eo_call_stack_get();
+   Eo_Call_Stack *stack = _eo_call_stack_get(is_main_loop);
 
    Eina_Bool class_ref = _eo_is_a_class(stack->frame_ptr->eo_id);
 
@@ -926,7 +932,7 @@ Eo *
 _eo_add_internal_end(Eo *eo_id)
 {
    Eo_Stack_Frame *fptr;
-   Eo_Call_Stack *stack = _eo_call_stack_get();
+   Eo_Call_Stack *stack = _eo_call_stack_get(eina_main_loop_is());
 
    fptr = stack->frame_ptr;