Author: stefan2
Date: Sat Feb 21 12:38:27 2015
New Revision: 1661344
URL: http://svn.apache.org/r1661344
Log:
On the fsx-1.10 branch:
Optimize FSX' DAG walker such that we don't re-read nodes that are already
cached. Do this without extra cache lookups.
* subversion/libsvn_fs_x/dag_cache.c
(auto_clear_dag_cache): Tell the caller whether we decided to actually
clear the cache.
(dag_step): Use the extended functionality of auto_clear_dag_cache to
do lookup and insertion with usually a single cache access.
Also, drop the special treatment of cached txn nodes as they
are fully reusable now.
Modified:
subversion/branches/fsx-1.10/subversion/libsvn_fs_x/dag_cache.c
Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/dag_cache.c
URL:
http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/dag_cache.c?rev=1661344&r1=1661343&r2=1661344&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/dag_cache.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/dag_cache.c Sat Feb 21
12:38:27 2015
@@ -295,18 +295,22 @@ svn_fs_x__create_dag_cache(apr_pool_t *r
return result;
}
-/* Clears the CACHE at regular intervals (destroying all cached nodes)
+/* Clears the CACHE at regular intervals (destroying all cached nodes).
+ * Return TRUE if the cache got cleared and previously obtained references
+ * to cache contents have become invalid.
*/
-static void
+static svn_boolean_t
auto_clear_dag_cache(svn_fs_x__dag_cache_t* cache)
{
- if (cache->insertions > BUCKET_COUNT)
- {
- svn_pool_clear(cache->pool);
+ if (cache->insertions <= BUCKET_COUNT)
+ return FALSE;
- memset(cache->buckets, 0, sizeof(cache->buckets));
- cache->insertions = 0;
- }
+ svn_pool_clear(cache->pool);
+
+ memset(cache->buckets, 0, sizeof(cache->buckets));
+ cache->insertions = 0;
+
+ return TRUE;
}
/* For the given CHANGE_SET and PATH, return the respective entry in CACHE.
@@ -598,6 +602,16 @@ dag_step(dag_node_t **child_p,
cache_entry_t *bucket;
svn_fs_x__id_t node_id;
+ /* Locate the corresponding cache entry. We may need PARENT to remain
+ valid for later use, so don't call auto_clear_dag_cache() here. */
+ bucket = cache_lookup(ffd->dag_node_cache, change_set, path);
+ if (bucket->node)
+ {
+ /* Already cached. Return a reference to the cached object. */
+ *child_p = bucket->node;
+ return SVN_NO_ERROR;
+ }
+
/* Get the ID of the node we are looking for. The function call checks
for various error conditions such like PARENT not being a directory. */
SVN_ERR(svn_fs_x__dir_entry_id(&node_id, parent, name, scratch_pool));
@@ -609,16 +623,16 @@ dag_step(dag_node_t **child_p,
return SVN_FS__NOT_FOUND(root, dir);
}
- /* Auto-insert the node in the cache. */
- auto_clear_dag_cache(ffd->dag_node_cache);
- bucket = cache_lookup(ffd->dag_node_cache, change_set, path);
-
- /* If it is not already cached, construct the DAG node object for NODE_ID.
- Let it live in the cache. Sadly, we often can't reuse txn DAG nodes. */
- if (bucket->node == NULL || root->is_txn_root)
- SVN_ERR(svn_fs_x__dag_get_node(&bucket->node, fs, &node_id,
- ffd->dag_node_cache->pool,
- scratch_pool));
+ /* We are about to add a new entry to the cache. Periodically clear it.
+ If we had to clear it just now (< 1% chance), re-add the entry for our
+ item. */
+ if (auto_clear_dag_cache(ffd->dag_node_cache))
+ bucket = cache_lookup(ffd->dag_node_cache, change_set, path);
+
+ /* Construct the DAG node object for NODE_ID. Let it live in the cache. */
+ SVN_ERR(svn_fs_x__dag_get_node(&bucket->node, fs, &node_id,
+ ffd->dag_node_cache->pool,
+ scratch_pool));
/* Return a reference to the cached object. */
*child_p = bucket->node;