[ovs-dev] [PATCH 2/5] lib/cmap: More efficient cmap_find().

Jarno Rajahalme jrajahalme at nicira.com
Wed Sep 24 18:31:44 UTC 2014


    These makes cmap_find 10% faster on GCC 4.7 (-O2 -g).

Signed-off-by: Jarno Rajahalme <jrajahalme at nicira.com>
---
 lib/cmap.c |   44 +++++++++++++++++++++++++++-----------------
 1 file changed, 27 insertions(+), 17 deletions(-)

diff --git a/lib/cmap.c b/lib/cmap.c
index ba744cc..fa7c0bb 100644
--- a/lib/cmap.c
+++ b/lib/cmap.c
@@ -304,35 +304,45 @@ cmap_find(const struct cmap *cmap, uint32_t hash)
     struct cmap_bucket *b2;
     uint32_t c1, c2;
     int i;
+    struct cmap_node *node;
 
-retry:
     b1 = &impl->buckets[h1 & impl->mask];
+    b2 = &impl->buckets[h2 & impl->mask];
+retry:
+    node = NULL;
     c1 = read_even_counter(b1);
     for (i = 0; i < CMAP_K; i++) {
-        struct cmap_node *node = cmap_node_next(&b1->nodes[i]);
-
-        if (node && cmap_get_hash(&b1->hashes[i]) == hash) {
-            if (counter_changed(b1, c1)) {
-                goto retry;
-            }
-            return node;
+        if (cmap_get_hash(&b1->hashes[i]) == hash) {
+            node = cmap_node_next(&b1->nodes[i]);
+            break;
         }
     }
+    if (OVS_UNLIKELY(counter_changed(b1, c1))) {
+        goto retry;
+    }
+    if (node) {
+        return node;
+    }
 
-    b2 = &impl->buckets[h2 & impl->mask];
+retry2:
+    node = NULL;
     c2 = read_even_counter(b2);
     for (i = 0; i < CMAP_K; i++) {
-        struct cmap_node *node = cmap_node_next(&b2->nodes[i]);
-
-        if (node && cmap_get_hash(&b2->hashes[i]) == hash) {
-            if (counter_changed(b2, c2)) {
-                goto retry;
-            }
-            return node;
+        if (cmap_get_hash(&b2->hashes[i]) == hash) {
+            node = cmap_node_next(&b2->nodes[i]);
+            break;
         }
     }
+    if (OVS_UNLIKELY(counter_changed(b2, c2))) {
+        goto retry2;
+    }
+    if (node) {
+        return node;
+    }
 
-    if (counter_changed(b1, c1) || counter_changed(b2, c2)) {
+    /* We just got a stable reading on 'b2', but a node could have been moved
+     * to 'b1', so we need to chack the 'c1' again. */
+    if (counter_changed(b1, c1)) {
         goto retry;
     }
     return NULL;
-- 
1.7.10.4




More information about the dev mailing list