Hi,

here are 2 patches to speed up eina_share_common_del with minimal costs on
eina_share_common_add side.

the second might be controversial

0001-eina_share_common_del-speed-up.patch
  builtin node is never unlinked even if empty,
  always is the last of the queue,
  so that it can be used to get a pointer to head.

  cost: never unlink or promote builtin node.
  benefit: no need to hash and search rbtree to unlink an empty node,
  only to remove an empty head.

0002-eina_share_common_del-speed-up.patch
  store full hash in Eina_Share_Common_Head, so we only hash once
  use 8 lower bits as node hash, use next 8 bits as bucket index.

  cost: have to apply 0xFF mask on hash in rbtree callbacks.
  benefit: no need to hash when removing an empty head.


regards
Jérémy
>From b8dbbedd49e8c66ff1fe201706c1e6a805f009f5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Zurcher?= <jer...@asynk.ch>
Date: Tue, 20 Nov 2012 22:31:46 +0100
Subject: [PATCH 1/2] eina_share_common_del speed up

builtin node is never unlinked even if empty,
always is the last of the queue,
so that it can be used to get a pointer to head.

cost: never unlink or promote builtin node.
benefit: no need to hash and search rbtree to unlink an empty node,
only to remove an empty head.
---
 efl/src/lib/eina/eina_share_common.c | 50 ++++++++++++++++++++++++------------
 1 file changed, 34 insertions(+), 16 deletions(-)

diff --git a/efl/src/lib/eina/eina_share_common.c 
b/efl/src/lib/eina/eina_share_common.c
index c68e399..bc9ea4b 100644
--- a/efl/src/lib/eina/eina_share_common.c
+++ b/efl/src/lib/eina/eina_share_common.c
@@ -477,10 +477,13 @@ _eina_share_common_head_find(Eina_Share_Common_Head *head,
    for (; node; prev = node, node = node->next)
       if (_eina_share_common_node_eq(node, str, slen))
         {
-           /* promote node, make hot items be at the beginning */
-           prev->next = node->next;
-           node->next = head->head;
-           head->head = node;
+           /* promote node except builtin_node, make hot items be at the 
beginning */
+           if (node->next)
+             {
+                prev->next = node->next;
+                node->next = head->head;
+                head->head = node;
+             }
            return node;
         }
 
@@ -519,6 +522,20 @@ _eina_share_common_find_hash(Eina_Share_Common_Head 
*bucket, int hash)
              EINA_RBTREE_CMP_KEY_CB(_eina_share_common_cmp), NULL);
 }
 
+static Eina_Share_Common_Head *
+_eina_share_common_head_from_node(Eina_Share_Common_Node *node)
+{
+   Eina_Share_Common_Head *head;
+   const size_t offset = offsetof(Eina_Share_Common_Head, builtin_node);
+
+   while (node->next)
+     node = node->next;
+   head = (Eina_Share_Common_Head *)((char*)node - offset);
+   EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(head, , 0);
+
+   return head;
+}
+
 static Eina_Share_Common_Node *
 _eina_share_common_node_alloc(unsigned int slen, unsigned int null_size)
 {
@@ -834,25 +851,26 @@ eina_share_common_del(Eina_Share *share, const char *str)
 
    node->references = 0;
 
-   hash = eina_hash_superfast(str, slen);
-   hash_num = hash & 0xFF;
-   hash = (hash >> 8) & EINA_SHARE_COMMON_MASK;
-
-   p_bucket = share->share->buckets + hash_num;
-   ed = _eina_share_common_find_hash(*p_bucket, hash);
+   ed = _eina_share_common_head_from_node(node);
    if (!ed)
       goto on_error;
 
    EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(ed, eina_lock_release(&_mutex_big), 
EINA_FALSE);
 
-   if (!_eina_share_common_head_remove_node(ed, node))
-      goto on_error;
-
    if (node != &ed->builtin_node)
-      MAGIC_FREE(node);
+     {
+        if (!_eina_share_common_head_remove_node(ed, node))
+          goto on_error;
+        MAGIC_FREE(node);
+     }
 
-   if (!ed->head)
-      _eina_share_common_del_head(p_bucket, ed);
+   if (!ed->head || ed->head->references == 0)
+     {
+        hash = eina_hash_superfast(str, slen);
+        hash_num = hash & 0xFF;
+        p_bucket = share->share->buckets + hash_num;
+        _eina_share_common_del_head(p_bucket, ed);
+     }
    else
       _eina_share_common_population_head_del(share, ed);
 
-- 
1.8.0

>From dbe93a06190383b3e4ba283d6453398bcf7c324a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Zurcher?= <jer...@asynk.ch>
Date: Tue, 20 Nov 2012 23:07:16 +0100
Subject: [PATCH 2/2] eina_share_common_del speed up

store full hash in Eina_Share_Common_Head, so we only hash once
use 8 lower bits as node hash, use next 8 bits as bucket index.

cost: have to apply 0xFF mask on hash in rbtree callbacks.
benefit: no need to hash when removing an empty head.
---
 efl/src/lib/eina/eina_share_common.c | 19 ++++++++-----------
 1 file changed, 8 insertions(+), 11 deletions(-)

diff --git a/efl/src/lib/eina/eina_share_common.c 
b/efl/src/lib/eina/eina_share_common.c
index bc9ea4b..2244df8 100644
--- a/efl/src/lib/eina/eina_share_common.c
+++ b/efl/src/lib/eina/eina_share_common.c
@@ -92,6 +92,8 @@
 
 #define EINA_SHARE_COMMON_BUCKETS 256
 #define EINA_SHARE_COMMON_MASK 0xFF
+#define EINA_SHARE_COMMON_BUCKET_IDX(h) ((h >> 8) & EINA_SHARE_COMMON_MASK)
+#define EINA_SHARE_COMMON_NODE_HASH(h) (h & EINA_SHARE_COMMON_MASK)
 
 static const char EINA_MAGIC_SHARE_STR[] = "Eina Share";
 static const char EINA_MAGIC_SHARE_HEAD_STR[] = "Eina Share Head";
@@ -342,7 +344,7 @@ _eina_share_common_cmp(const Eina_Share_Common_Head *ed,
 {
    EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(ed, , 0);
 
-   return ed->hash - *hash;
+   return EINA_SHARE_COMMON_NODE_HASH(ed->hash) - *hash;
 }
 
 static Eina_Rbtree_Direction
@@ -353,7 +355,7 @@ _eina_share_common_node(const Eina_Share_Common_Head *left,
    EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(left,  , 0);
    EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(right, , 0);
 
-   if (left->hash - right->hash < 0)
+   if (EINA_SHARE_COMMON_NODE_HASH(left->hash) - 
EINA_SHARE_COMMON_NODE_HASH(right->hash) < 0)
       return EINA_RBTREE_LEFT;
 
    return EINA_RBTREE_RIGHT;
@@ -737,7 +739,7 @@ eina_share_common_add_length(Eina_Share *share,
 {
    Eina_Share_Common_Head **p_bucket, *ed;
    Eina_Share_Common_Node *el;
-   int hash_num, hash;
+   int hash;
 
    if (!str)
       return NULL;
@@ -748,13 +750,11 @@ eina_share_common_add_length(Eina_Share *share,
       return NULL;
 
    hash = eina_hash_superfast(str, slen);
-   hash_num = hash & 0xFF;
-   hash = (hash >> 8) & EINA_SHARE_COMMON_MASK;
 
    eina_lock_take(&_mutex_big);
-   p_bucket = share->share->buckets + hash_num;
+   p_bucket = share->share->buckets + EINA_SHARE_COMMON_BUCKET_IDX(hash);
 
-   ed = _eina_share_common_find_hash(*p_bucket, hash);
+   ed = _eina_share_common_find_hash(*p_bucket, 
EINA_SHARE_COMMON_NODE_HASH(hash));
    if (!ed)
      {
         const char *s = _eina_share_common_add_head(share,
@@ -829,7 +829,6 @@ eina_share_common_del(Eina_Share *share, const char *str)
    Eina_Share_Common_Head *ed;
    Eina_Share_Common_Head **p_bucket;
    Eina_Share_Common_Node *node;
-   int hash_num, hash;
 
    if (!str)
       return EINA_TRUE;
@@ -866,9 +865,7 @@ eina_share_common_del(Eina_Share *share, const char *str)
 
    if (!ed->head || ed->head->references == 0)
      {
-        hash = eina_hash_superfast(str, slen);
-        hash_num = hash & 0xFF;
-        p_bucket = share->share->buckets + hash_num;
+        p_bucket = share->share->buckets + 
EINA_SHARE_COMMON_BUCKET_IDX(ed->hash);
         _eina_share_common_del_head(p_bucket, ed);
      }
    else
-- 
1.8.0

------------------------------------------------------------------------------
Monitor your physical, virtual and cloud infrastructure from a single
web console. Get in-depth insight into apps, servers, databases, vmware,
SAP, cloud infrastructure, etc. Download 30-day Free Trial.
Pricing starts from $795 for 25 servers or applications!
http://p.sf.net/sfu/zoho_dev2dev_nov
_______________________________________________
enlightenment-devel mailing list
enlightenment-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel

Reply via email to