subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From stef...@apache.org
Subject svn commit: r1325870 - /subversion/trunk/subversion/libsvn_subr/cache-membuffer.c
Date Fri, 13 Apr 2012 17:52:59 GMT
Author: stefan2
Date: Fri Apr 13 17:52:59 2012
New Revision: 1325870

URL: http://svn.apache.org/viewvc?rev=1325870&view=rev
Log:
Minimize hash key creation overhead by directly applying MD5 instead of 
copying / duplicating the key. Also, check for NULL keys directly on the interface.

* subversion/libsvn_subr/cache-membuffer.c
  (get_group_index): don't calculate the 16 byte hash; require it to come in
  (membuffer_cache_set, membuffer_cache_get,
   membuffer_cache_get_partial, membuffer_cache_set_partial):
   adapt callers; invalid groups are impossible now
  (svn_membuffer_cache_t): ensure proper alignment for prefix;
   add temp buffer for combined key
  (combine_key): calculate & combine hashes
  (svn_membuffer_cache_get, svn_membuffer_cache_set,
   svn_membuffer_cache_get_partial, svn_membuffer_cache_set_partial):
   adapt callers; handle NULL keys

Modified:
    subversion/trunk/subversion/libsvn_subr/cache-membuffer.c

Modified: subversion/trunk/subversion/libsvn_subr/cache-membuffer.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/cache-membuffer.c?rev=1325870&r1=1325869&r2=1325870&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/cache-membuffer.c (original)
+++ subversion/trunk/subversion/libsvn_subr/cache-membuffer.c Fri Apr 13 17:52:59 2012
@@ -589,38 +589,21 @@ insert_entry(svn_membuffer_t *cache, ent
  */
 static apr_uint32_t
 get_group_index(svn_membuffer_t **cache,
-                const void *key,
-                apr_size_t len,
-                unsigned char *to_find,
+                const apr_uint32_t *key,
                 apr_pool_t *pool)
 {
-  apr_uint32_t hash = 0;
-  int i;
-
-  /* calculate a hash value for the key */
-  svn_checksum_t *checksum;
-  svn_error_t *err;
-
-  if (key == NULL)
-    return NO_INDEX;
-
-  err = svn_checksum(&checksum, svn_checksum_md5, key, len, pool);
-  if (err != NULL)
-  {
-    svn_error_clear(err);
-    return NO_INDEX;
-  }
-
-  memcpy(to_find, checksum->digest, APR_MD5_DIGESTSIZE);
-
-  /* select the cache segment to use */
-  *cache = &(*cache)[to_find[0] & ((*cache)->segment_count -1)];
+  apr_uint32_t hash;
 
   /* Get the group that *must* contain the entry. Fold the hash value
    * just to be sure (it should not be necessary for perfect hashes).
    */
-  for (i = 0; i < sizeof(to_find) / sizeof(apr_uint32_t); ++i)
-    hash += ((apr_uint32_t*)to_find)[i] ^ ((hash >> 19) || (hash << 13));
+  hash = key[0];
+  hash = key[1] ^ ((hash >> 19) || (hash << 13));
+  hash = key[2] ^ ((hash >> 19) || (hash << 13));
+  hash = key[3] ^ ((hash >> 19) || (hash << 13));
+
+  /* select the cache segment to use */
+  *cache = &(*cache)[key[0] & ((*cache)->segment_count -1)];
 
   return hash % (*cache)->group_count;
 }
@@ -1154,22 +1137,18 @@ membuffer_cache_set_internal(svn_membuff
 static svn_error_t *
 membuffer_cache_set(svn_membuffer_t *cache,
                     const void *key,
-                    apr_size_t key_len,
                     void *item,
                     svn_cache__serialize_func_t serializer,
                     DEBUG_CACHE_MEMBUFFER_TAG_ARG
                     apr_pool_t *scratch_pool)
 {
   apr_uint32_t group_index;
-  unsigned char to_find[KEY_SIZE];
   void *buffer = NULL;
   apr_size_t size;
 
   /* find the entry group that will hold the key.
    */
-  group_index = get_group_index(&cache, key, key_len, to_find, scratch_pool);
-  if (group_index == NO_INDEX)
-    return SVN_NO_ERROR;
+  group_index = get_group_index(&cache, key, scratch_pool);
 
   /* Serialize data data.
    */
@@ -1180,7 +1159,7 @@ membuffer_cache_set(svn_membuffer_t *cac
    */
   SVN_MUTEX__WITH_LOCK(cache->mutex,
                        membuffer_cache_set_internal(cache,
-                                                    to_find,
+                                                    key,
                                                     group_index,
                                                     buffer,
                                                     size,
@@ -1262,32 +1241,22 @@ membuffer_cache_get_internal(svn_membuff
 static svn_error_t *
 membuffer_cache_get(svn_membuffer_t *cache,
                     const void *key,
-                    apr_size_t key_len,
                     void **item,
                     svn_cache__deserialize_func_t deserializer,
                     DEBUG_CACHE_MEMBUFFER_TAG_ARG
                     apr_pool_t *result_pool)
 {
   apr_uint32_t group_index;
-  unsigned char to_find[KEY_SIZE];
   char *buffer;
   apr_size_t size;
 
   /* find the entry group that will hold the key.
    */
-  group_index = get_group_index(&cache, key, key_len, to_find, result_pool);
-  if (group_index == NO_INDEX)
-    {
-      /* Some error occured, return "item not found".
-       */
-      *item = NULL;
-      return SVN_NO_ERROR;
-    }
-
+  group_index = get_group_index(&cache, key, result_pool);
   SVN_MUTEX__WITH_LOCK(cache->mutex,
                        membuffer_cache_get_internal(cache,
                                                     group_index,
-                                                    to_find,
+                                                    key,
                                                     &buffer,
                                                     &size,
                                                     DEBUG_CACHE_MEMBUFFER_TAG
@@ -1378,7 +1347,6 @@ membuffer_cache_get_partial_internal(svn
 static svn_error_t *
 membuffer_cache_get_partial(svn_membuffer_t *cache,
                             const void *key,
-                            apr_size_t key_len,
                             void **item,
                             svn_boolean_t *found,
                             svn_cache__partial_getter_func_t deserializer,
@@ -1386,17 +1354,13 @@ membuffer_cache_get_partial(svn_membuffe
                             DEBUG_CACHE_MEMBUFFER_TAG_ARG
                             apr_pool_t *result_pool)
 {
-  apr_uint32_t group_index;
-  unsigned char to_find[KEY_SIZE];
+  apr_uint32_t group_index = get_group_index(&cache, key, result_pool);
 
-  group_index = get_group_index(&cache, key, key_len, to_find, result_pool);
-
-  if (group_index != NO_INDEX)
-    SVN_MUTEX__WITH_LOCK(cache->mutex,
-                         membuffer_cache_get_partial_internal
-                             (cache, group_index, to_find, item, found,
-                              deserializer, baton, DEBUG_CACHE_MEMBUFFER_TAG
-                              result_pool));
+  SVN_MUTEX__WITH_LOCK(cache->mutex,
+                       membuffer_cache_get_partial_internal
+                           (cache, group_index, key, item, found,
+                            deserializer, baton, DEBUG_CACHE_MEMBUFFER_TAG
+                            result_pool));
 
   return SVN_NO_ERROR;
 }
@@ -1515,25 +1479,19 @@ membuffer_cache_set_partial_internal(svn
 static svn_error_t *
 membuffer_cache_set_partial(svn_membuffer_t *cache,
                             const void *key,
-                            apr_size_t key_len,
                             svn_cache__partial_setter_func_t func,
                             void *baton,
                             DEBUG_CACHE_MEMBUFFER_TAG_ARG
                             apr_pool_t *scratch_pool)
 {
-  apr_uint32_t group_index;
-  unsigned char to_find[KEY_SIZE];
-
   /* cache item lookup
    */
-  group_index = get_group_index(&cache, key, key_len, to_find, scratch_pool);
-
-  if (group_index != NO_INDEX)
-    SVN_MUTEX__WITH_LOCK(cache->mutex,
-                         membuffer_cache_set_partial_internal
-                             (cache, group_index, to_find, func, baton,
-                              DEBUG_CACHE_MEMBUFFER_TAG_ARG
-                              scratch_pool));
+  apr_uint32_t group_index = get_group_index(&cache, key, scratch_pool);
+  SVN_MUTEX__WITH_LOCK(cache->mutex,
+                       membuffer_cache_set_partial_internal
+                           (cache, group_index, key, func, baton,
+                            DEBUG_CACHE_MEMBUFFER_TAG_ARG
+                            scratch_pool));
 
   /* done here -> unlock the cache
    */
@@ -1576,7 +1534,7 @@ typedef struct svn_membuffer_cache_t
    * This makes (very likely) our keys different from all keys used
    * by other svn_membuffer_cache_t instances.
    */
-  unsigned char prefix [APR_MD5_DIGESTSIZE];
+  apr_uint64_t prefix [APR_MD5_DIGESTSIZE / sizeof(apr_uint64_t)];
 
   /* A copy of the unmodified prefix. It is being used as a user-visible
    * ID for this cache instance.
@@ -1588,6 +1546,10 @@ typedef struct svn_membuffer_cache_t
    */
   apr_ssize_t key_len;
 
+  /* Temporary buffer containing the hash key for the current access
+   */
+  apr_uint64_t combined_key [APR_MD5_DIGESTSIZE / sizeof(apr_uint64_t)];
+
   /* a pool for temporary allocations during get() and set()
    */
   apr_pool_t *pool;
@@ -1619,30 +1581,17 @@ typedef struct svn_membuffer_cache_t
  * Allocations will be made in POOL.
  */
 static void
-combine_key(const void *prefix,
-            apr_size_t prefix_len,
+combine_key(svn_membuffer_cache_t *cache,
             const void *key,
-            apr_ssize_t key_len,
-            void **full_key,
-            apr_size_t *full_key_len,
-            apr_pool_t *pool)
+            apr_ssize_t key_len)
 {
-  if (key == NULL)
-    {
-      *full_key = NULL;
-      *full_key_len = 0;
-    }
-  else
-    {
-      if (key_len == APR_HASH_KEY_STRING)
-        key_len = strlen((const char *) key);
+  if (key_len == APR_HASH_KEY_STRING)
+    key_len = strlen((const char *) key);
 
-      *full_key_len = prefix_len + key_len;
-      *full_key = apr_palloc(pool, *full_key_len);
+  apr_md5((unsigned char*)cache->combined_key, key, key_len);
 
-      memcpy(*full_key, prefix, prefix_len);
-      memcpy((char *)*full_key + prefix_len, key, key_len);
-    }
+  cache->combined_key[0] ^= cache->prefix[0];
+  cache->combined_key[1] ^= cache->prefix[1];
 }
 
 /* Implement svn_cache__vtable_t.get (not thread-safe)
@@ -1656,26 +1605,25 @@ svn_membuffer_cache_get(void **value_p,
 {
   svn_membuffer_cache_t *cache = cache_void;
 
+  DEBUG_CACHE_MEMBUFFER_INIT_TAG
+
+  /* special case */
+  if (key == NULL)
+    {
+      *value_p = NULL;
+      *found = FALSE;
+      
+      return SVN_NO_ERROR;
+    }
+
   /* construct the full, i.e. globally unique, key by adding
    * this cache instances' prefix
    */
-  void *full_key;
-  apr_size_t full_key_len;
-
-  DEBUG_CACHE_MEMBUFFER_INIT_TAG
-
-  combine_key(cache->prefix,
-              sizeof(cache->prefix),
-              key,
-              cache->key_len,
-              &full_key,
-              &full_key_len,
-              cache->pool);
+  combine_key(cache, key, cache->key_len);
 
   /* Look the item up. */
   SVN_ERR(membuffer_cache_get(cache->membuffer,
-                              full_key,
-                              full_key_len,
+                              cache->combined_key,
                               value_p,
                               cache->deserializer,
                               DEBUG_CACHE_MEMBUFFER_TAG
@@ -1706,11 +1654,12 @@ svn_membuffer_cache_set(void *cache_void
 {
   svn_membuffer_cache_t *cache = cache_void;
 
-  void *full_key;
-  apr_size_t full_key_len;
-
   DEBUG_CACHE_MEMBUFFER_INIT_TAG
 
+  /* special case */
+  if (key == NULL)
+    return SVN_NO_ERROR;
+
   /* we do some allocations below, so increase the allocation counter
    * by a slightly larger amount. Free allocated memory every now and then.
    */
@@ -1724,20 +1673,13 @@ svn_membuffer_cache_set(void *cache_void
   /* construct the full, i.e. globally unique, key by adding
    * this cache instances' prefix
    */
-  combine_key(cache->prefix,
-              sizeof(cache->prefix),
-              key,
-              cache->key_len,
-              &full_key,
-              &full_key_len,
-              cache->pool);
+  combine_key(cache, key, cache->key_len);
 
   /* (probably) add the item to the cache. But there is no real guarantee
    * that the item will actually be cached afterwards.
    */
   return membuffer_cache_set(cache->membuffer,
-                             full_key,
-                             full_key_len,
+                             cache->combined_key,
                              value,
                              cache->serializer,
                              DEBUG_CACHE_MEMBUFFER_TAG
@@ -1770,28 +1712,25 @@ svn_membuffer_cache_get_partial(void **v
 {
   svn_membuffer_cache_t *cache = cache_void;
 
-  void *full_key;
-  apr_size_t full_key_len;
-
   DEBUG_CACHE_MEMBUFFER_INIT_TAG
 
+  if (key == NULL)
+    {
+      *value_p = NULL;
+      *found = FALSE;
+
+      return SVN_NO_ERROR;
+    }
+
   if (++cache->alloc_counter > ALLOCATIONS_PER_POOL_CLEAR)
     {
       apr_pool_clear(cache->pool);
       cache->alloc_counter = 0;
     }
 
-  combine_key(cache->prefix,
-              sizeof(cache->prefix),
-              key,
-              cache->key_len,
-              &full_key,
-              &full_key_len,
-              cache->pool);
-
+  combine_key(cache, key, cache->key_len);
   SVN_ERR(membuffer_cache_get_partial(cache->membuffer,
-                                      full_key,
-                                      full_key_len,
+                                      cache->combined_key,
                                       value_p,
                                       found,
                                       func,
@@ -1813,27 +1752,18 @@ svn_membuffer_cache_set_partial(void *ca
 {
   svn_membuffer_cache_t *cache = cache_void;
 
-  void *full_key;
-  apr_size_t full_key_len;
-
   DEBUG_CACHE_MEMBUFFER_INIT_TAG
 
-  combine_key(cache->prefix,
-              sizeof(cache->prefix),
-              key,
-              cache->key_len,
-              &full_key,
-              &full_key_len,
-              scratch_pool);
-
-  SVN_ERR(membuffer_cache_set_partial(cache->membuffer,
-                                      full_key,
-                                      full_key_len,
-                                      func,
-                                      baton,
-                                      DEBUG_CACHE_MEMBUFFER_TAG
-                                      scratch_pool));
-
+  if (key != NULL)
+    {
+      combine_key(cache, key, cache->key_len);
+      SVN_ERR(membuffer_cache_set_partial(cache->membuffer,
+                                          cache->combined_key,
+                                          func,
+                                          baton,
+                                          DEBUG_CACHE_MEMBUFFER_TAG
+                                          scratch_pool));
+    }
   return SVN_NO_ERROR;
 }
 



Mime
View raw message