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.
 


Reply via email to