[or-cvs] r11012: Split over-optimized digestmap_set code into a generic part (in tor/trunk: . src/common)

nickm at seul.org nickm at seul.org
Wed Aug 1 15:57:49 UTC 2007


Author: nickm
Date: 2007-08-01 11:57:48 -0400 (Wed, 01 Aug 2007)
New Revision: 11012

Modified:
   tor/trunk/
   tor/trunk/src/common/container.c
   tor/trunk/src/common/ht.h
Log:
 r13873 at Kushana:  nickm | 2007-07-31 10:54:05 -0700
 Split over-optimized digestmap_set code into a generic part and a digestmap-specific part.



Property changes on: tor/trunk
___________________________________________________________________
 svk:merge ticket from /tor/trunk [r13873] on c95137ef-5f19-0410-b913-86e773d04f59

Modified: tor/trunk/src/common/container.c
===================================================================
--- tor/trunk/src/common/container.c	2007-08-01 15:57:34 UTC (rev 11011)
+++ tor/trunk/src/common/container.c	2007-08-01 15:57:48 UTC (rev 11012)
@@ -769,8 +769,6 @@
 {
 #ifndef OPTIMIZED_DIGESTMAP_SET
   digestmap_entry_t *resolve;
-#else
-  digestmap_entry_t **resolve_ptr;
 #endif
   digestmap_entry_t search;
   void *oldval;
@@ -792,31 +790,28 @@
     return NULL;
   }
 #else
-  /* XXXX020 We spend up to 5% of our time in this function, so the code
-   * below is meant to optimize the check/alloc/set cycle by avoiding the
-   * two trips to the hash table that we do in the unoptimized code above.
-   * (Each of HT_INSERT and HT_FIND calls HT_SET_HASH and HT_FIND_P.)
-   *
-   * Unfortunately, doing this requires us to poke around inside hash-table
-   * internals.  It would be nice to avoid that. */
-  if (!map->head.hth_table ||
-      map->head.hth_n_entries >= map->head.hth_load_limit)
-    digestmap_impl_HT_GROW((&map->head), map->head.hth_n_entries+1);
-  _HT_SET_HASH(&search, node, digestmap_entry_hash);
-  resolve_ptr = _digestmap_impl_HT_FIND_P(&map->head, &search);
-  if (*resolve_ptr) {
-    oldval = (*resolve_ptr)->val;
-    (*resolve_ptr)->val = val;
-    return oldval;
-  } else {
-    digestmap_entry_t *newent = tor_malloc_zero(sizeof(digestmap_entry_t));
-    memcpy(newent->key, key, DIGEST_LEN);
-    newent->val = val;
-    newent->node.hte_hash = search.node.hte_hash;
-    *resolve_ptr = newent;
-    ++map->head.hth_n_entries;
-    return NULL;
-  }
+  /* We spend up to 5% of our time in this function, so the code below is
+   * meant to optimize the check/alloc/set cycle by avoiding the two trips to
+   * the hash table that we do in the unoptimized code above.  (Each of
+   * HT_INSERT and HT_FIND calls HT_SET_HASH and HT_FIND_P.)
+   */
+  _HT_FIND_OR_INSERT(digestmap_impl, node, digestmap_entry_hash, &(map->head),
+         digestmap_entry_t, &search, ptr,
+         {
+            /* we found an entry. */
+            oldval = (*ptr)->val;
+            (*ptr)->val = val;
+            return oldval;
+         },
+         {
+           /* We didn't find the entry. */
+           digestmap_entry_t *newent =
+             tor_malloc_zero(sizeof(digestmap_entry_t));
+           memcpy(newent->key, key, DIGEST_LEN);
+           newent->val = val;
+           _HT_FOI_INSERT(node, &(map->head), &search, newent, ptr);
+           return NULL;
+         });
 #endif
 }
 

Modified: tor/trunk/src/common/ht.h
===================================================================
--- tor/trunk/src/common/ht.h	2007-08-01 15:57:34 UTC (rev 11011)
+++ tor/trunk/src/common/ht.h	2007-08-01 15:57:48 UTC (rev 11012)
@@ -382,6 +382,31 @@
     return 0;                                                           \
   }
 
+/** Implements an over-optimized "find and insert if absent" block;
+ * not meant for direct usage by typical code, or usage outside the critical
+ * path.*/
+#define _HT_FIND_OR_INSERT(name, field, hashfn, head, eltype, elm, var, y, n) \
+  {                                                                     \
+    struct name *_##var##_head = head;                                  \
+    eltype **var;                                                       \
+    if (!_##var##_head->hth_table ||                                    \
+        _##var##_head->hth_n_entries >= _##var##_head->hth_load_limit)  \
+      name##_HT_GROW(_##var##_head, _##var##_head->hth_n_entries+1);     \
+    _HT_SET_HASH((elm), field, hashfn);                                \
+    var = _##name##_HT_FIND_P(_##var##_head, (elm));                    \
+    if (*var) {                                                         \
+      y;                                                                \
+    } else {                                                            \
+      n;                                                                \
+    }                                                                   \
+  }
+#define _HT_FOI_INSERT(field, head, elm, newent, var)       \
+  {                                                         \
+    newent->field.hte_hash = (elm)->field.hte_hash;         \
+    *var = newent;                                          \
+    ++((head)->hth_n_entries);                              \
+  }
+
 /*
  * Copyright 2005, Nick Mathewson.  Implementation logic is adapted from code
  * by Cristopher Clark, retrofit to allow drop-in memory management, and to



More information about the tor-commits mailing list