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 2013/11/27 08:19:47 UTC

svn commit: r1545948 - /subversion/trunk/subversion/libsvn_subr/cache-membuffer.c

Author: stefan2
Date: Wed Nov 27 07:19:47 2013
New Revision: 1545948

URL: http://svn.apache.org/r1545948
Log:
Make the membuffer cache accept even large items if they are important
enough.  By allowing large items to be directly inserted into L2, we
can accept larger objects than before.  The item size limit is now
about 4 times the previous value.

This almost exclusively benefits directories that those are the only
large non-low-prio objects that we handle.  Since cache eviction rules
still apply, it may take multiple attempts (i.e. accesses) until L2
has been cleaned out enough to leave room for the new object.  But
frequently used, large directories will eventually get cached.

* subversion/libsvn_subr/cache-membuffer.c
  (select_level): New utility that determines where items should
                  be inserted.
  (membuffer_cache_set_internal): Let the new utility function select the
                                  cache level for the new item instead of
                                  always using L1.
  (svn_membuffer_cache_is_cachable): Indicate that we also allow for
                                     large important items to be cached.

Modified:
    subversion/trunk/subversion/libsvn_subr/cache-membuffer.c

Modified: subversion/trunk/subversion/libsvn_subr/cache-membuffer.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/cache-membuffer.c?rev=1545948&r1=1545947&r2=1545948&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/cache-membuffer.c (original)
+++ subversion/trunk/subversion/libsvn_subr/cache-membuffer.c Wed Nov 27 07:19:47 2013
@@ -1817,6 +1817,39 @@ entry_exists(svn_membuffer_t *cache,
   return SVN_NO_ERROR;
 }
 
+/* Given the SIZE and PRIORITY of a new item, return the cache level
+   (L1 or L2) in fragment CACHE that this item shall be inserted into.
+   If we can't find nor make enough room for the item, return NULL.
+ */
+static cache_level_t *
+select_level(svn_membuffer_t *cache,
+             apr_size_t size,
+             apr_uint32_t priority)
+{
+  if (cache->max_entry_size >= size)
+    {
+      /* Small items go into L1. */
+      return ensure_data_insertable_l1(cache, size)
+           ? &cache->l1
+           : NULL;
+    }
+  else if (   cache->l2.size >= size
+           && MAX_ITEM_SIZE >= size
+           && priority >= SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY)
+    {
+      /* Large and somewhat important items go into L2. */
+      entry_t dummy_entry = { 0 };
+      dummy_entry.priority = priority;
+      dummy_entry.size = size;
+
+      return ensure_data_insertable_l2(cache, &dummy_entry)
+           ? &cache->l2
+           : NULL;
+    }
+
+  /* Don't cache large, unimportant items. */
+  return NULL;
+}
 
 /* Try to insert the serialized item given in BUFFER with SIZE into
  * the group GROUP_INDEX of CACHE and uniquely identify it by hash
@@ -1840,6 +1873,8 @@ membuffer_cache_set_internal(svn_membuff
                              DEBUG_CACHE_MEMBUFFER_TAG_ARG
                              apr_pool_t *scratch_pool)
 {
+  cache_level_t *level;
+
   /* first, look for a previous entry for the given key */
   entry_t *entry = find_entry(cache, group_index, to_find, FALSE);
 
@@ -1869,9 +1904,8 @@ membuffer_cache_set_internal(svn_membuff
 
   /* if necessary, enlarge the insertion window.
    */
-  if (   buffer != NULL
-      && cache->max_entry_size >= size
-      && ensure_data_insertable_l1(cache, size))
+  level = buffer ? select_level(cache, size, priority) : NULL;
+  if (level)
     {
       /* Remove old data for this key, if that exists.
        * Get an unused entry for the key and and initialize it with
@@ -1879,7 +1913,7 @@ membuffer_cache_set_internal(svn_membuff
        */
       entry = find_entry(cache, group_index, to_find, TRUE);
       entry->size = size;
-      entry->offset = cache->l1.current_data;
+      entry->offset = level->current_data;
       entry->priority = priority;
 
 #ifdef SVN_DEBUG_CACHE_MEMBUFFER
@@ -2774,7 +2808,9 @@ svn_membuffer_cache_is_cachable(void *ca
    * must be small enough to be stored in a 32 bit value.
    */
   svn_membuffer_cache_t *cache = cache_void;
-  return size <= cache->membuffer->max_entry_size;
+  return cache->priority >= SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY
+       ? cache->membuffer->l2.size >= size && MAX_ITEM_SIZE >= size
+       : size <= cache->membuffer->max_entry_size;
 }
 
 /* Add statistics of SEGMENT to INFO.  If INCLUDE_HISTOGRAM is TRUE,