Author: rhuijben
Date: Thu May 31 19:36:34 2012
New Revision: 1344875
URL: http://svn.apache.org/viewvc?rev=1344875&view=rev
Log:
Optimize svn_client_propget4() for the case where we retrieve a specific
current property for all descendants of a node. This saves 10% CPU on the
ra_local mergeinfo tests and also on my profile testcase of
svn merge ^/subversion/trunk -c "1293945,1293972,1293976,1293998,1294136,
1294236,1294134,1294147,1294586" into 1.7.x.
* subversion/include/private/svn_wc_private.h
(svn_wc__prop_retrieve_recursive): New function.
* subversion/libsvn_client/prop_commands.c
(get_prop_from_wc): Return an hash, instead of filling one. Add an optimized
case.
(svn_client_propget4): Update caller.
* subversion/libsvn_wc/props.c
(svn_wc__prop_retrieve_recursive): New function.
* subversion/libsvn_wc/wc-queries.sql
(STMT_SELECT_CURRENT_PROPS_RECURSIVE): New query.
* subversion/libsvn_wc/wc_db.c
(svn_wc__db_prop_retrieve_recursive): New function.
* subversion/libsvn_wc/wc_db.h
(svn_wc__db_prop_retrieve_recursive): New function.
Modified:
subversion/trunk/subversion/include/private/svn_wc_private.h
subversion/trunk/subversion/libsvn_client/prop_commands.c
subversion/trunk/subversion/libsvn_wc/props.c
subversion/trunk/subversion/libsvn_wc/wc-queries.sql
subversion/trunk/subversion/libsvn_wc/wc_db.c
subversion/trunk/subversion/libsvn_wc/wc_db.h
Modified: subversion/trunk/subversion/include/private/svn_wc_private.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/include/private/svn_wc_private.h?rev=1344875&r1=1344874&r2=1344875&view=diff
==============================================================================
--- subversion/trunk/subversion/include/private/svn_wc_private.h (original)
+++ subversion/trunk/subversion/include/private/svn_wc_private.h Thu May 31
19:36:34 2012
@@ -916,6 +916,20 @@ svn_wc__prop_list_recursive(svn_wc_conte
void *cancel_baton,
apr_pool_t *scratch_pool);
+/** Obtain a mapping of const char * local_abspaths to const svn_string_t*
+ * property values in *VALUES, of all PROPNAME properties on LOCAL_ABSPATH
+ * and its descendants.
+ *
+ * Allocate the result in RESULT_POOL, and perform temporary allocations in
+ * SCRATCH_POOL.
+ */
+svn_error_t *
+svn_wc__prop_retrieve_recursive(apr_hash_t **values,
+ svn_wc_context_t *wc_ctx,
+ const char *local_abspath,
+ const char *propname,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
/**
* For use by entries.c and entries-dump.c to read old-format working copies.
Modified: subversion/trunk/subversion/libsvn_client/prop_commands.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/prop_commands.c?rev=1344875&r1=1344874&r2=1344875&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/prop_commands.c (original)
+++ subversion/trunk/subversion/libsvn_client/prop_commands.c Thu May 31
19:36:34 2012
@@ -743,7 +743,7 @@ recursive_propget_receiver(void *baton,
Treat DEPTH as in svn_client_propget3().
*/
static svn_error_t *
-get_prop_from_wc(apr_hash_t *props,
+get_prop_from_wc(apr_hash_t **props,
const char *propname,
const char *target_abspath,
svn_boolean_t pristine,
@@ -764,7 +764,19 @@ get_prop_from_wc(apr_hash_t *props,
if (depth == svn_depth_unknown)
depth = svn_depth_infinity;
- rb.props = props;
+ if (!pristine && depth == svn_depth_infinity
+ && (!changelists || changelists->nelts == 0))
+ {
+ /* Handle this common svn:mergeinfo case more efficient than the target
+ list handling in the recursive retrieval. */
+ SVN_ERR(svn_wc__prop_retrieve_recursive(
+ props, ctx->wc_ctx, target_abspath, propname,
+ result_pool, scratch_pool));
+ return SVN_NO_ERROR;
+ }
+
+ *props = apr_hash_make(result_pool);
+ rb.props = *props;
rb.pool = result_pool;
rb.wc_ctx = ctx->wc_ctx;
@@ -802,8 +814,6 @@ svn_client_propget4(apr_hash_t **props,
target);
revision = svn_cl__rev_default_to_peg(revision, peg_revision);
- *props = apr_hash_make(result_pool);
-
if (! svn_path_is_url(target)
&& SVN_CLIENT__REVKIND_IS_LOCAL_TO_WC(peg_revision->kind)
&& SVN_CLIENT__REVKIND_IS_LOCAL_TO_WC(revision->kind))
@@ -840,7 +850,7 @@ svn_client_propget4(apr_hash_t **props,
else if (err)
return svn_error_trace(err);
- SVN_ERR(get_prop_from_wc(*props, propname, target,
+ SVN_ERR(get_prop_from_wc(props, propname, target,
pristine, kind,
depth, changelists, ctx, scratch_pool,
result_pool));
@@ -859,6 +869,7 @@ svn_client_propget4(apr_hash_t **props,
SVN_ERR(svn_ra_check_path(ra_session, "", loc->rev, &kind,
scratch_pool));
+ *props = apr_hash_make(result_pool);
SVN_ERR(remote_propget(*props, propname, loc->url, "",
kind, loc->rev, ra_session,
depth, result_pool, scratch_pool));
Modified: subversion/trunk/subversion/libsvn_wc/props.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/props.c?rev=1344875&r1=1344874&r2=1344875&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/props.c (original)
+++ subversion/trunk/subversion/libsvn_wc/props.c Thu May 31 19:36:34 2012
@@ -1909,6 +1909,22 @@ svn_wc__prop_list_recursive(svn_wc_conte
}
svn_error_t *
+svn_wc__prop_retrieve_recursive(apr_hash_t **values,
+ svn_wc_context_t *wc_ctx,
+ const char *local_abspath,
+ const char *propname,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ return svn_error_trace(
+ svn_wc__db_prop_retrieve_recursive(values,
+ wc_ctx->db,
+ local_abspath,
+ propname,
+ result_pool, scratch_pool));
+}
+
+svn_error_t *
svn_wc__get_pristine_props(apr_hash_t **props,
svn_wc__db_t *db,
const char *local_abspath,
Modified: subversion/trunk/subversion/libsvn_wc/wc-queries.sql
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc-queries.sql?rev=1344875&r1=1344874&r2=1344875&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/trunk/subversion/libsvn_wc/wc-queries.sql Thu May 31 19:36:34
2012
@@ -1041,6 +1041,16 @@ FROM nodes_current n
WHERE wc_id = ?1 AND IS_STRICT_DESCENDANT_OF(local_relpath, ?2)
AND kind = 'dir' AND presence IN ('normal', 'incomplete')
+-- STMT_SELECT_CURRENT_PROPS_RECURSIVE
+/* ### Ugly OR to make sqlite use the proper optimizations */
+SELECT IFNULL((SELECT properties FROM actual_node a
+ WHERE a.wc_id = ?1 AND A.local_relpath = n.local_relpath),
+ properties),
+ local_relpath
+FROM nodes_current n
+WHERE (wc_id = ?1 AND local_relpath = ?2)
+ OR (wc_id = ?1 AND IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
+
/* ------------------------------------------------------------------------- */
/* these are used in entries.c */
Modified: subversion/trunk/subversion/libsvn_wc/wc_db.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.c?rev=1344875&r1=1344874&r2=1344875&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.c Thu May 31 19:36:34 2012
@@ -8466,6 +8466,66 @@ svn_wc__db_read_pristine_props(apr_hash_
return SVN_NO_ERROR;
}
+svn_error_t *
+svn_wc__db_prop_retrieve_recursive(apr_hash_t **values,
+ svn_wc__db_t *db,
+ const char *local_abspath,
+ const char *propname,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_wc__db_wcroot_t *wcroot;
+ const char *local_relpath;
+ svn_sqlite__stmt_t *stmt;
+ svn_boolean_t have_row;
+ apr_pool_t *iterpool;
+
+ SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
+
+ SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
+ local_abspath, scratch_pool, scratch_pool));
+ VERIFY_USABLE_WCROOT(wcroot);
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+ STMT_SELECT_CURRENT_PROPS_RECURSIVE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
+
+ *values = apr_hash_make(result_pool);
+
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ iterpool = svn_pool_create(scratch_pool);
+ while (have_row)
+ {
+ apr_hash_t *node_props;
+ svn_string_t *value;
+
+ svn_pool_clear(iterpool);
+
+ SVN_ERR(svn_sqlite__column_properties(&node_props, stmt, 0,
+ iterpool, iterpool));
+
+ value = (node_props
+ ? apr_hash_get(node_props, propname, APR_HASH_KEY_STRING)
+ : NULL);
+
+ if (value)
+ {
+ apr_hash_set(*values,
+ svn_dirent_join(wcroot->abspath,
+ svn_sqlite__column_text(stmt, 1, NULL),
+ result_pool),
+ APR_HASH_KEY_STRING,
+ svn_string_dup(value, result_pool));
+ }
+
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ }
+
+ svn_pool_destroy(iterpool);
+
+ return svn_error_trace(svn_sqlite__reset(stmt));
+}
+
svn_error_t *
svn_wc__db_read_children_of_working_node(const apr_array_header_t **children,
Modified: subversion/trunk/subversion/libsvn_wc/wc_db.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.h?rev=1344875&r1=1344874&r2=1344875&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.h Thu May 31 19:36:34 2012
@@ -2059,6 +2059,22 @@ svn_wc__db_read_pristine_props(apr_hash_
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
+
+/** Obtain a mapping of const char * local_abspaths to const svn_string_t*
+ * property values in *VALUES, of all PROPNAME properties on LOCAL_ABSPATH
+ * and its descendants.
+ *
+ * Allocate the result in RESULT_POOL, and perform temporary allocations in
+ * SCRATCH_POOL.
+ */
+svn_error_t *
+svn_wc__db_prop_retrieve_recursive(apr_hash_t **values,
+ svn_wc__db_t *db,
+ const char *local_abspath,
+ const char *propname,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
/* Set *CHILDREN to a new array of the (const char *) basenames of the
immediate children of the working node at LOCAL_ABSPATH in DB.