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 2014/02/13 20:59:20 UTC
svn commit: r1568022 - in /subversion/branches/1.8.x-r1567996: ./
subversion/libsvn_subr/cache-membuffer.c
Author: stefan2
Date: Thu Feb 13 19:59:20 2014
New Revision: 1568022
URL: http://svn.apache.org/r1568022
Log:
Merge r1567996 and r1568009 from /trunk and resolve text conflicts.
Modified:
subversion/branches/1.8.x-r1567996/ (props changed)
subversion/branches/1.8.x-r1567996/subversion/libsvn_subr/cache-membuffer.c
Propchange: subversion/branches/1.8.x-r1567996/
------------------------------------------------------------------------------
Merged /subversion/trunk:r1567996,1568009
Modified: subversion/branches/1.8.x-r1567996/subversion/libsvn_subr/cache-membuffer.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.8.x-r1567996/subversion/libsvn_subr/cache-membuffer.c?rev=1568022&r1=1568021&r2=1568022&view=diff
==============================================================================
--- subversion/branches/1.8.x-r1567996/subversion/libsvn_subr/cache-membuffer.c (original)
+++ subversion/branches/1.8.x-r1567996/subversion/libsvn_subr/cache-membuffer.c Thu Feb 13 19:59:20 2014
@@ -88,6 +88,12 @@
* with new entries. For details on the fine-tuning involved, see the
* comments in ensure_data_insertable().
*
+ * Reads will update hit counts without synchronization, i.e. some updates
+ * will be lost and mostly so on the segment-global counters because read
+ * conflicts are more common on them. I.e. sum(entry.hits) > cache->hits.
+ * Thus, we must check for underflows when removing or aging an entry and
+ * update the segment-global hit counter.
+ *
* To limit the entry size and management overhead, not the actual item keys
* but only their MD5 checksums will not be stored. This is reasonably safe
* to do since users have only limited control over the full keys, even if
@@ -641,8 +647,10 @@ drop_entry(svn_membuffer_t *cache, entry
/* update global cache usage counters
*/
cache->used_entries--;
- cache->hit_count -= entry->hit_count;
- cache->data_used -= entry->size;
+ if (cache->hit_count > entry->hit_count)
+ cache->hit_count -= entry->hit_count;
+ else
+ cache->hit_count = 0;
/* extend the insertion window, if the entry happens to border it
*/
@@ -802,7 +810,11 @@ let_entry_age(svn_membuffer_t *cache, en
{
apr_uint32_t hits_removed = (entry->hit_count + 1) >> 1;
- cache->hit_count -= hits_removed;
+ if (cache->hit_count > hits_removed)
+ cache->hit_count -= hits_removed;
+ else
+ cache->hit_count = 0;
+
entry->hit_count -= hits_removed;
}
@@ -1484,6 +1496,24 @@ membuffer_cache_set(svn_membuffer_t *cac
return SVN_NO_ERROR;
}
+/* Count a hit in ENTRY within CACHE.
+ */
+static void
+increment_hit_counters(svn_membuffer_t *cache, entry_t *entry)
+{
+ /* To minimize the memory footprint of the cache index, we limit local
+ * hit counters to 32 bits. These may overflow and we must make sure that
+ * the global sums are still (roughly due to races) the sum of all local
+ * counters. */
+ if (++entry->hit_count == 0)
+ cache->hit_count -= APR_UINT32_MAX;
+ else
+ cache->hit_count++;
+
+ /* That one is for stats only. */
+ cache->total_hits++;
+}
+
/* Look for the cache entry in group GROUP_INDEX of CACHE, identified
* by the hash value TO_FIND. If no item has been stored for KEY,
* *BUFFER will be NULL. Otherwise, return a copy of the serialized
@@ -1540,10 +1570,7 @@ membuffer_cache_get_internal(svn_membuff
/* update hit statistics
*/
- entry->hit_count++;
- cache->hit_count++;
- cache->total_hits++;
-
+ increment_hit_counters(cache, entry);
*item_size = entry->size;
return SVN_NO_ERROR;
@@ -1624,9 +1651,7 @@ membuffer_cache_get_partial_internal(svn
{
*found = TRUE;
- entry->hit_count++;
- cache->hit_count++;
- cache->total_hits++;
+ increment_hit_counters(cache, entry);
#ifdef SVN_DEBUG_CACHE_MEMBUFFER
@@ -1716,8 +1741,7 @@ membuffer_cache_set_partial_internal(svn
char *orig_data = data;
apr_size_t size = entry->size;
- entry->hit_count++;
- cache->hit_count++;
+ increment_hit_counters(cache, entry);
cache->total_writes++;
#ifdef SVN_DEBUG_CACHE_MEMBUFFER