summaryrefslogtreecommitdiff
path: root/subversion/libsvn_fs_fs/tree.c
diff options
context:
space:
mode:
authorPeter Wemm <peter@FreeBSD.org>2013-07-28 05:04:41 +0000
committerPeter Wemm <peter@FreeBSD.org>2013-07-28 05:04:41 +0000
commit97551b2898eb459e9b616947d87d026d27b61518 (patch)
treea851d66ec0c51a7321b30a677a0e55f1655af4d6 /subversion/libsvn_fs_fs/tree.c
parentfec88c40a7bace625f49c3234a71560a161ee0ef (diff)
Diffstat (limited to 'subversion/libsvn_fs_fs/tree.c')
-rw-r--r--subversion/libsvn_fs_fs/tree.c37
1 files changed, 32 insertions, 5 deletions
diff --git a/subversion/libsvn_fs_fs/tree.c b/subversion/libsvn_fs_fs/tree.c
index c14955d737b8c..64c8395295a81 100644
--- a/subversion/libsvn_fs_fs/tree.c
+++ b/subversion/libsvn_fs_fs/tree.c
@@ -151,7 +151,7 @@ typedef struct cache_entry_t
{
/* hash value derived from PATH, REVISION.
Used to short-circuit failed lookups. */
- long int hash_value;
+ apr_uint32_t hash_value;
/* revision to which the NODE belongs */
svn_revnum_t revision;
@@ -340,7 +340,12 @@ cache_lookup( fs_fs_dag_cache_t *cache
{
apr_size_t i, bucket_index;
apr_size_t path_len = strlen(path);
- long int hash_value = revision;
+ apr_uint32_t hash_value = (apr_uint32_t)revision;
+
+#if SVN_UNALIGNED_ACCESS_IS_OK
+ /* "randomizing" / distributing factor used in our hash function */
+ const apr_uint32_t factor = 0xd1f3da69;
+#endif
/* optimistic lookup: hit the same bucket again? */
cache_entry_t *result = &cache->buckets[cache->last_hit];
@@ -353,11 +358,25 @@ cache_lookup( fs_fs_dag_cache_t *cache
/* need to do a full lookup. Calculate the hash value
(HASH_VALUE has been initialized to REVISION). */
- for (i = 0; i + 4 <= path_len; i += 4)
- hash_value = hash_value * 0xd1f3da69 + *(const apr_uint32_t*)(path + i);
+ i = 0;
+#if SVN_UNALIGNED_ACCESS_IS_OK
+ /* We relax the dependency chain between iterations by processing
+ two chunks from the input per hash_value self-multiplication.
+ The HASH_VALUE update latency is now 1 MUL latency + 1 ADD latency
+ per 2 chunks instead of 1 chunk.
+ */
+ for (; i + 8 <= path_len; i += 8)
+ hash_value = hash_value * factor * factor
+ + ( *(const apr_uint32_t*)(path + i) * factor
+ + *(const apr_uint32_t*)(path + i + 4));
+#endif
for (; i < path_len; ++i)
- hash_value = hash_value * 33 + path[i];
+ /* Help GCC to minimize the HASH_VALUE update latency by splitting the
+ MUL 33 of the naive implementation: h = h * 33 + path[i]. This
+ shortens the dependency chain from 1 shift + 2 ADDs to 1 shift + 1 ADD.
+ */
+ hash_value = hash_value * 32 + (hash_value + (unsigned char)path[i]);
bucket_index = hash_value + (hash_value >> 16);
bucket_index = (bucket_index + (bucket_index >> 8)) % BUCKET_COUNT;
@@ -3364,6 +3383,14 @@ fs_node_origin_rev(svn_revnum_t *revision,
return SVN_NO_ERROR;
}
+ /* The root node always has ID 0, created in revision 0 and will never
+ use the new-style ID format. */
+ if (strcmp(node_id, "0") == 0)
+ {
+ *revision = 0;
+ return SVN_NO_ERROR;
+ }
+
/* OK, it's an old-style ID? Maybe it's cached. */
SVN_ERR(svn_fs_fs__get_node_origin(&cached_origin_id,
fs,