Author: stefan2
Date: Sat Jan 19 22:49:11 2013
New Revision: 1435749

URL: http://svn.apache.org/viewvc?rev=1435749&view=rev
Log:
Speed up svn_fs_fs__verify() by making verify_walker() reuse open rev
and pack file handles between iterations.  That gives a 3x speedup.

* subversion/libsvn_fs_fs/fs_fs.c
  (svn_fs_fs__verify): new optinal baton type
  (verify_walker): if baton is provided, reuse file handles between calls
  (svn_fs_fs__verify): provide verify_walker() with a baton

Modified:
    subversion/trunk/subversion/libsvn_fs_fs/fs_fs.c

Modified: subversion/trunk/subversion/libsvn_fs_fs/fs_fs.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/fs_fs.c?rev=1435749&r1=1435748&r2=1435749&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/fs_fs.c Sat Jan 19 22:49:11 2013
@@ -10289,6 +10289,28 @@ svn_fs_fs__pack(svn_fs_t *fs,
 
 /** Verifying. **/
 
+/* Baton type expected by verify_walker().  The purpose is to reuse open
+ * rev / pack file handles between calls.  Its contents need to be cleaned
+ * periodically to limit resource usage.
+ */
+typedef struct verify_walker_baton_t
+{
+  /* number of calls to verify_walker() since the last clean */
+  int iteration_count;
+  
+  /* number of files opened since the last clean */
+  int file_count;
+
+  /* current file handle (or NULL) */
+  apr_file_t *file_hint;
+
+  /* corresponding revision (or SVN_INVALID_REVNUM) */
+  svn_revnum_t rev_hint;
+
+  /* pool to use for the file handles etc. */
+  apr_pool_t *pool;
+} verify_walker_baton_t;
+
 /* Used by svn_fs_fs__verify().
    Implements svn_fs_fs__walk_rep_reference().walker.  */
 static svn_error_t *
@@ -10300,13 +10322,40 @@ verify_walker(representation_t *rep,
   struct rep_state *rs;
   struct rep_args *rep_args;
 
-#ifdef SVN_DEBUG
-  /* verify_walker() is called directly by get_shared_rep() with baton=NULL. */
-  SVN_ERR_ASSERT(!baton);
-#endif
+  if (baton)
+    {
+      verify_walker_baton_t *walker_baton = baton;
+      apr_file_t * previous_file;
+
+      /* free resources periodically */
+      if (   walker_baton->iteration_count > 1000
+          || walker_baton->file_count > 16)
+        {
+          svn_pool_clear(walker_baton->pool);
+          
+          walker_baton->iteration_count = 0;
+          walker_baton->file_count = 0;
+          walker_baton->file_hint = NULL;
+          walker_baton->rev_hint = SVN_INVALID_REVNUM;
+        }
 
-  /* ### Should this be using read_rep_line() directly? */
-  SVN_ERR(create_rep_state(&rs, &rep_args, NULL, NULL, rep, fs, scratch_pool));
+      /* access the repo data */
+      previous_file = walker_baton->file_hint;
+      SVN_ERR(create_rep_state(&rs, &rep_args, &walker_baton->file_hint,
+                               &walker_baton->rev_hint, rep, fs,
+                               walker_baton->pool));
+
+      /* update resource usage counters */
+      walker_baton->iteration_count++;
+      if (previous_file != walker_baton->file_hint)
+        walker_baton->file_count++;
+    }
+  else
+    {
+      /* ### Should this be using read_rep_line() directly? */
+      SVN_ERR(create_rep_state(&rs, &rep_args, NULL, NULL, rep, fs,
+                               scratch_pool));
+    }
 
   return SVN_NO_ERROR;
 }
@@ -10339,14 +10388,25 @@ svn_fs_fs__verify(svn_fs_t *fs,
   /* rep-cache verification. */
   SVN_ERR(svn_fs_fs__exists_rep_cache(&exists, fs, pool));
   if (exists)
-    /* Do not attempt to walk the rep-cache database if its file does not 
exist,
-       since doing so would create it --- which may confuse the administrator.
-       Don't take any lock. */
-    SVN_ERR(svn_fs_fs__walk_rep_reference(fs, verify_walker, NULL,
-                                          cancel_func, cancel_baton,
-                                          notify_func, notify_baton,
-                                          start, end,
-                                          pool));
+    {
+      /* provide a baton to allow the reuse of open file handles between
+         iterations (saves 2/3 of OS level file operations). */
+      verify_walker_baton_t *baton = apr_pcalloc(pool, sizeof(*baton));
+      baton->rev_hint = SVN_INVALID_REVNUM;
+      baton->pool = svn_pool_create(pool);
+      
+      /* Do not attempt to walk the rep-cache database if its file does
+         not exist,  since doing so would create it --- which may confuse
+         the administrator.   Don't take any lock. */
+      SVN_ERR(svn_fs_fs__walk_rep_reference(fs, verify_walker, baton,
+                                            cancel_func, cancel_baton,
+                                            notify_func, notify_baton,
+                                            start, end,
+                                            pool));
+
+      /* walker resource cleanup */
+      svn_pool_destroy(baton->pool);
+    }
 
   return SVN_NO_ERROR;
 }


Reply via email to