You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2010/11/21 21:14:09 UTC

svn commit: r1037548 - in /subversion/branches/performance/subversion/libsvn_fs_fs: caching.c fs.h fs_fs.c id.c id.h

Author: stefan2
Date: Sun Nov 21 20:14:09 2010
New Revision: 1037548

URL: http://svn.apache.org/viewvc?rev=1037548&view=rev
Log:
Address issues from http://svn.haxx.se/dev/archive-2010-10/0499.shtml
It's not actually necessary to tag the cached revision root IDs with
"belongs to packed / non-packed rev". Use separate caches for these
cases, instead.

The reason that this works is that there can be only one transition from
non-packed to packed and that this is not reversible (see comments in
code for more details).

* subversion/libsvn_fs_fs/id.h
  (svn_fs_fs__is_packed, svn_fs_fs__set_packed): drop 
* subversion/libsvn_fs_fs/id.c
  (id_private_t): remove is_packed member
  (svn_fs_fs__id_txn_create, svn_fs_fs__id_rev_create, svn_fs_fs__id_copy,
   svn_fs_fs__id_parse): remove references to that member
  (svn_fs_fs__is_packed, svn_fs_fs__set_packed): drop

* subversion/libsvn_fs_fs/fs.h
  (fs_fs_data_t): add separate cache for packed revision root IDs
* subversion/libsvn_fs_fs/fs_fs.c
  (svn_fs_fs__rev_get_root): access right ID cache; drop the ID modification
* subversion/libsvn_fs_fs/caching.c
  (svn_fs_fs__initialize_caches): initialize new cache

Modified:
    subversion/branches/performance/subversion/libsvn_fs_fs/caching.c
    subversion/branches/performance/subversion/libsvn_fs_fs/fs.h
    subversion/branches/performance/subversion/libsvn_fs_fs/fs_fs.c
    subversion/branches/performance/subversion/libsvn_fs_fs/id.c
    subversion/branches/performance/subversion/libsvn_fs_fs/id.h

Modified: subversion/branches/performance/subversion/libsvn_fs_fs/caching.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_fs_fs/caching.c?rev=1037548&r1=1037547&r2=1037548&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_fs_fs/caching.c (original)
+++ subversion/branches/performance/subversion/libsvn_fs_fs/caching.c Sun Nov 21 20:14:09 2010
@@ -115,32 +115,53 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
                             close_unused_file_handles,
                             apr_pool_cleanup_null);
 
-  /* Make the cache for revision roots.  For the vast majority of
-   * commands, this is only going to contain a few entries (svnadmin
-   * dump/verify is an exception here), so to reduce overhead let's
-   * try to keep it to just one page.  I estimate each entry has about
-   * 72 bytes of overhead (svn_revnum_t key, svn_fs_id_t +
+  /* Make the caches for non-packed and packed revision roots.  For the
+   * vastmajority of commands, this is only going to contain a few entries
+   * (svnadmin dump/verify is an exception here), so to reduce overhead
+   * let's try to keep it to just one page.  I estimate each entry has
+   * about 72 bytes of overhead (svn_revnum_t key, svn_fs_id_t +
    * id_private_t + 3 strings for value, and the cache_entry); the
    * default pool size is 8192, so about a hundred should fit
    * comfortably. */
   if (svn_fs__get_global_membuffer_cache())
-    SVN_ERR(svn_cache__create_membuffer_cache(&(ffd->rev_root_id_cache),
-                                              svn_fs__get_global_membuffer_cache(),
-                                              svn_fs_fs__serialize_id,
-                                              svn_fs_fs__deserialize_id,
-                                              sizeof(svn_revnum_t),
-                                              apr_pstrcat(pool, prefix, "RRI",
+    {
+      SVN_ERR(svn_cache__create_membuffer_cache(&(ffd->rev_root_id_cache),
+                                                svn_fs__get_global_membuffer_cache(),
+                                                svn_fs_fs__serialize_id,
+                                                svn_fs_fs__deserialize_id,
+                                                sizeof(svn_revnum_t),
+                                                apr_pstrcat(pool, prefix, "RRI",
+                                                            (char *)NULL),
+                                                fs->pool));
+      SVN_ERR(svn_cache__create_membuffer_cache(&(ffd->packed_rev_root_id_cache),
+                                                svn_fs__get_global_membuffer_cache(),
+                                                svn_fs_fs__serialize_id,
+                                                svn_fs_fs__deserialize_id,
+                                                sizeof(svn_revnum_t),
+                                                apr_pstrcat(pool, prefix, "PRRI",
                                                           (char *)NULL),
-                                              fs->pool));
+                                                fs->pool));
+    }
   else
-    SVN_ERR(svn_cache__create_inprocess(&(ffd->rev_root_id_cache),
-                                        svn_fs_fs__serialize_id,
-                                        svn_fs_fs__deserialize_id,
-                                        sizeof(svn_revnum_t),
-                                        1, 100, FALSE, fs->pool));
+    {
+      SVN_ERR(svn_cache__create_inprocess(&(ffd->rev_root_id_cache),
+                                          svn_fs_fs__serialize_id,
+                                          svn_fs_fs__deserialize_id,
+                                          sizeof(svn_revnum_t),
+                                          1, 100, FALSE, fs->pool));
+      SVN_ERR(svn_cache__create_inprocess(&(ffd->packed_rev_root_id_cache),
+                                          svn_fs_fs__serialize_id,
+                                          svn_fs_fs__deserialize_id,
+                                          sizeof(svn_revnum_t),
+                                          1, 100, FALSE, fs->pool));
+    }
   if (! no_handler)
-    SVN_ERR(svn_cache__set_error_handler(ffd->rev_root_id_cache,
-                                         warn_on_cache_errors, fs, pool));
+    {
+      SVN_ERR(svn_cache__set_error_handler(ffd->rev_root_id_cache,
+                                          warn_on_cache_errors, fs, pool));
+      SVN_ERR(svn_cache__set_error_handler(ffd->packed_rev_root_id_cache,
+                                          warn_on_cache_errors, fs, pool));
+    }
 
 
   /* Rough estimate: revision DAG nodes have size around 320 bytes, so

Modified: subversion/branches/performance/subversion/libsvn_fs_fs/fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_fs_fs/fs.h?rev=1037548&r1=1037547&r2=1037548&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_fs_fs/fs.h (original)
+++ subversion/branches/performance/subversion/libsvn_fs_fs/fs.h Sun Nov 21 20:14:09 2010
@@ -226,9 +226,15 @@ typedef struct
      multiple svn_fs_t's for the same filesystem.) */
 
   /* A cache of revision root IDs, mapping from (svn_revnum_t *) to
-     (svn_fs_id_t *).  (Not threadsafe.) */
+     (svn_fs_id_t *). Some of the IDs may belong to non-packed revs
+     but these will never be read. This is guaranteed by the fact
+     that the transition from non-packed to packed is irreversable. */
   svn_cache__t *rev_root_id_cache;
 
+  /* Similar to @ref rev_root_id_cache but all IDs are guaranteed
+     to belong to packed revisions. */
+  svn_cache__t *packed_rev_root_id_cache;
+
   /* DAG node cache for immutable nodes */
   svn_cache__t *rev_node_cache;
 

Modified: subversion/branches/performance/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_fs_fs/fs_fs.c?rev=1037548&r1=1037547&r2=1037548&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/performance/subversion/libsvn_fs_fs/fs_fs.c Sun Nov 21 20:14:09 2010
@@ -2974,17 +2974,23 @@ svn_fs_fs__rev_get_root(svn_fs_id_t **ro
   svn_file_handle_cache__handle_t *revision_file;
   apr_file_t *apr_rev_file;
   apr_off_t root_offset;
+  svn_cache__t *cache = NULL;
   svn_fs_id_t *root_id = NULL;
   svn_boolean_t is_cached;
-  svn_tristate_t is_packed;
 
   SVN_ERR(ensure_revision_exists(fs, rev, pool));
 
+  /* Try to find the ID in our caches.  Once we tried is_packed_rev
+     returned true, we will never try to use the cache for non-packed
+     revs again.  Also, if we find the entry in the cache, this 
+     function cannot be racy because we don't need to access the file. */
+  cache = is_packed_rev(fs, rev)
+        ? ffd->packed_rev_root_id_cache
+        : ffd->rev_root_id_cache;
   SVN_ERR(svn_cache__get((void **) root_id_p, &is_cached,
-                         ffd->rev_root_id_cache, &rev, pool));
+                         cache, &rev, pool));
 
-  is_packed = is_packed_rev(fs, rev) ? svn_tristate_true : svn_tristate_false;
-  if (is_cached && is_packed == svn_fs_fs__is_packed(*root_id_p))
+  if (is_cached)
     return SVN_NO_ERROR;
 
   /* we don't care about the file pointer position */
@@ -2998,13 +3004,13 @@ svn_fs_fs__rev_get_root(svn_fs_id_t **ro
 
   SVN_ERR(get_fs_id_at_offset(&root_id, apr_rev_file, fs, rev, root_offset, 
                               pool));
-  svn_fs_fs__set_packed(root_id, is_packed_rev(fs, rev)
-                                    ? svn_tristate_true
-                                    : svn_tristate_false);
 
   SVN_ERR(svn_file_handle_cache__close(revision_file));
 
-  SVN_ERR(svn_cache__set(ffd->rev_root_id_cache, &rev, root_id, pool));
+  /* At this point, the revision might have already gotten packed
+     but cache is still the one for non-packed IDs.  In that case,
+     it will never be looked up here, again.  So, we are safe. */
+  SVN_ERR(svn_cache__set(cache, &rev, root_id, pool));
 
   *root_id_p = root_id;
 

Modified: subversion/branches/performance/subversion/libsvn_fs_fs/id.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_fs_fs/id.c?rev=1037548&r1=1037547&r2=1037548&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_fs_fs/id.c (original)
+++ subversion/branches/performance/subversion/libsvn_fs_fs/id.c Sun Nov 21 20:14:09 2010
@@ -34,7 +34,6 @@ typedef struct {
   const char *txn_id;
   svn_revnum_t rev;
   apr_off_t offset;
-  svn_tristate_t is_packed;
 } id_private_t;
 
 
@@ -85,24 +84,6 @@ svn_fs_fs__id_offset(const svn_fs_id_t *
 }
 
 
-svn_tristate_t
-svn_fs_fs__is_packed(const svn_fs_id_t *id)
-{
-  id_private_t *pvt = id->fsap_data;
-
-  return pvt->is_packed;
-}
-
-void
-svn_fs_fs__set_packed(const svn_fs_id_t *id,
-                      svn_tristate_t is_packed)
-{
-  id_private_t *pvt = id->fsap_data;
-
-  pvt->is_packed = is_packed;
-}
-
-
 svn_string_t *
 svn_fs_fs__id_unparse(const svn_fs_id_t *id,
                       apr_pool_t *pool)
@@ -206,7 +187,6 @@ svn_fs_fs__id_txn_create(const char *nod
   pvt->txn_id = apr_pstrdup(pool, txn_id);
   pvt->rev = SVN_INVALID_REVNUM;
   pvt->offset = -1;
-  pvt->is_packed = svn_tristate_unknown;
 
   id->vtable = &id_vtable;
   id->fsap_data = pvt;
@@ -229,7 +209,6 @@ svn_fs_fs__id_rev_create(const char *nod
   pvt->txn_id = NULL;
   pvt->rev = rev;
   pvt->offset = offset;
-  pvt->is_packed = svn_tristate_unknown;
 
   id->vtable = &id_vtable;
   id->fsap_data = pvt;
@@ -249,7 +228,6 @@ svn_fs_fs__id_copy(const svn_fs_id_t *id
   new_pvt->txn_id = pvt->txn_id ? apr_pstrdup(pool, pvt->txn_id) : NULL;
   new_pvt->rev = pvt->rev;
   new_pvt->offset = pvt->offset;
-  new_pvt->is_packed = pvt->is_packed;
 
   new_id->vtable = &id_vtable;
   new_id->fsap_data = new_pvt;
@@ -321,7 +299,6 @@ svn_fs_fs__id_parse(const char *data,
           return NULL;
         }
       pvt->offset = (apr_off_t)val;
-      pvt->is_packed = svn_tristate_unknown;
     }
   else if (str[0] == 't')
     {
@@ -329,7 +306,6 @@ svn_fs_fs__id_parse(const char *data,
       pvt->txn_id = str + 1;
       pvt->rev = SVN_INVALID_REVNUM;
       pvt->offset = -1;
-      pvt->is_packed = svn_tristate_unknown;
     }
   else
     return NULL;

Modified: subversion/branches/performance/subversion/libsvn_fs_fs/id.h
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_fs_fs/id.h?rev=1037548&r1=1037547&r2=1037548&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_fs_fs/id.h (original)
+++ subversion/branches/performance/subversion/libsvn_fs_fs/id.h Sun Nov 21 20:14:09 2010
@@ -49,12 +49,6 @@ svn_revnum_t svn_fs_fs__id_rev(const svn
    ID. */
 apr_off_t svn_fs_fs__id_offset(const svn_fs_id_t *id);
 
-/* Access the "is_packed" flag of the ID. */
-svn_tristate_t svn_fs_fs__is_packed(const svn_fs_id_t *id);
-
-/* Set the "is_packed" flag of the ID. */
-void svn_fs_fs__set_packed(const svn_fs_id_t *id, svn_tristate_t is_packed);
-
 /* Convert ID into string form, allocated in POOL. */
 svn_string_t *svn_fs_fs__id_unparse(const svn_fs_id_t *id,
                                     apr_pool_t *pool);