diff options
author | Peter Wemm <peter@FreeBSD.org> | 2013-07-28 05:04:41 +0000 |
---|---|---|
committer | Peter Wemm <peter@FreeBSD.org> | 2013-07-28 05:04:41 +0000 |
commit | 97551b2898eb459e9b616947d87d026d27b61518 (patch) | |
tree | a851d66ec0c51a7321b30a677a0e55f1655af4d6 /subversion/libsvn_fs_fs/tree.c | |
parent | fec88c40a7bace625f49c3234a71560a161ee0ef (diff) |
Diffstat (limited to 'subversion/libsvn_fs_fs/tree.c')
-rw-r--r-- | subversion/libsvn_fs_fs/tree.c | 37 |
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, |