[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[or-cvs] r10312: Optimize digestmap_set, since it sometimes shows up in profi (in tor/trunk: . src/common)



Author: nickm
Date: 2007-05-24 14:12:38 -0400 (Thu, 24 May 2007)
New Revision: 10312

Modified:
   tor/trunk/
   tor/trunk/src/common/container.c
   tor/trunk/src/common/ht.h
Log:
 r12933@catbus:  nickm | 2007-05-24 14:10:28 -0400
 Optimize digestmap_set, since it sometimes shows up in profiles.  Seems to work so far, but it isnt the prettiest thing ever.



Property changes on: tor/trunk
___________________________________________________________________
 svk:merge ticket from /tor/trunk [r12933] on 8246c3cf-6607-4228-993b-4d95d33730f1

Modified: tor/trunk/src/common/container.c
===================================================================
--- tor/trunk/src/common/container.c	2007-05-24 17:36:44 UTC (rev 10311)
+++ tor/trunk/src/common/container.c	2007-05-24 18:12:38 UTC (rev 10312)
@@ -748,20 +748,24 @@
   }
 }
 
+#define OPTIMIZED_DIGESTMAP_SET
+
 /** Like strmap_set() above but for digestmaps. */
 void *
 digestmap_set(digestmap_t *map, const char *key, void *val)
 {
-  /* XXXX We spend up to 5% of our time in this function. We should tighten
-   * it up... but not on the 0.1.2.x series; the HT code has historically
-   * been finicky and fragile. */
+#ifndef OPTIMIZED_DIGESTMAP_SET
   digestmap_entry_t *resolve;
+#else
+  digestmap_entry_t **resolve_ptr;
+#endif
   digestmap_entry_t search;
   void *oldval;
   tor_assert(map);
   tor_assert(key);
   tor_assert(val);
   memcpy(&search.key, key, DIGEST_LEN);
+#ifndef OPTIMIZED_DIGESTMAP_SET
   resolve = HT_FIND(digestmap_impl, &map->head, &search);
   if (resolve) {
     oldval = resolve->val;
@@ -774,6 +778,33 @@
     HT_INSERT(digestmap_impl, &map->head, resolve);
     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;
+  }
+#endif
 }
 
 /** Return the current value associated with <b>key</b>, or NULL if no

Modified: tor/trunk/src/common/ht.h
===================================================================
--- tor/trunk/src/common/ht.h	2007-05-24 17:36:44 UTC (rev 10311)
+++ tor/trunk/src/common/ht.h	2007-05-24 18:12:38 UTC (rev 10312)
@@ -80,7 +80,7 @@
 
 #define _HT_SET_HASH(elm, field, hashfn)        \
   do {                                          \
-    elm->field.hte_hash = hashfn(elm);          \
+    (elm)->field.hte_hash = hashfn(elm);        \
   } while (0)
 
 #define HT_FOREACH(x, name, head)                 \