You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by al...@apache.org on 2011/10/13 10:28:43 UTC

svn commit: r1182713 - in /jackrabbit/trunk/jackrabbit-core/src: main/java/org/apache/jackrabbit/core/cache/ main/java/org/apache/jackrabbit/core/persistence/bundle/ main/java/org/apache/jackrabbit/core/state/ test/java/org/apache/jackrabbit/core/cache/

Author: alexparvulescu
Date: Thu Oct 13 08:28:43 2011
New Revision: 1182713

URL: http://svn.apache.org/viewvc?rev=1182713&view=rev
Log:
JCR-3098 Add hit miss statistics and logging to caches
 - patch by Bart van der Schans

Modified:
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/AbstractCache.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/Cache.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/CacheAccessListener.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/CacheManager.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/ConcurrentCache.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/MLRUItemStateCache.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/cache/ConcurrentCacheTest.java

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/AbstractCache.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/AbstractCache.java?rev=1182713&r1=1182712&r2=1182713&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/AbstractCache.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/AbstractCache.java Thu Oct 13 08:28:43 2011
@@ -65,6 +65,22 @@ public abstract class AbstractCache impl
     private final AtomicLong accessCount = new AtomicLong();
 
     /**
+     * Cache access counter. Unike his counterpart {@link #accessCount}, this
+     * does not get reset.
+     * 
+     * It is used in the cases where a cache listener needs to call
+     * {@link Cache#resetAccessCount()}, but also needs a total access count. If
+     * you are sure that nobody calls reset, you can just use
+     * {@link #accessCount}.
+     */
+    private final AtomicLong totalAccessCount = new AtomicLong();
+
+    /**
+     * Cache miss counter.
+     */
+    private final AtomicLong missCount = new AtomicLong();
+
+    /**
      * Cache access listener. Set in the
      * {@link #setAccessListener(CacheAccessListener)} method and accessed
      * by periodically by the {@link #recordCacheAccess()} method.
@@ -102,9 +118,14 @@ public abstract class AbstractCache impl
         if (count % ACCESS_INTERVAL == 0) {
             CacheAccessListener listener = accessListener.get();
             if (listener != null) {
-                listener.cacheAccessed();
+                listener.cacheAccessed(count);
             }
         }
+        totalAccessCount.incrementAndGet();
+    }
+
+    protected void recordCacheMiss() {
+        missCount.incrementAndGet();
     }
 
     public long getAccessCount() {
@@ -114,6 +135,18 @@ public abstract class AbstractCache impl
     public void resetAccessCount() {
         accessCount.set(0);
     }
+    
+    public long getTotalAccessCount(){
+        return totalAccessCount.get();
+    }
+
+    public long getMissCount() {
+        return missCount.get();
+    }
+
+    public void resetMissCount() {
+        missCount.set(0);
+    }
 
     public long getMemoryUsed() {
         return memoryUsed.get();
@@ -146,4 +179,25 @@ public abstract class AbstractCache impl
         }
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    public String getCacheInfoAsString() {
+        long u = getMemoryUsed() / 1024;
+        long m = getMaxMemorySize() / 1024;
+        StringBuilder c = new StringBuilder();
+        c.append("Cache name=");
+        c.append(this.toString());
+        c.append(", elements=");
+        c.append(getElementCount());
+        c.append(", used memory=");
+        c.append(u);
+        c.append(", max memory=");
+        c.append(m);
+        c.append(", access=");
+        c.append(getTotalAccessCount());
+        c.append(", miss=");
+        c.append(getMissCount());
+        return c.toString();
+    }
 }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/Cache.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/Cache.java?rev=1182713&r1=1182712&r2=1182713&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/Cache.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/Cache.java Thu Oct 13 08:28:43 2011
@@ -45,7 +45,6 @@ public interface Cache {
      * Get the number of accesses (get or set) until resetAccessCount was called.
      * @return the count
      */
-
     long getAccessCount();
 
     /**
@@ -54,8 +53,37 @@ public interface Cache {
     void resetAccessCount();
 
     /**
+     * Get the total number of cache accesses.
+     * @return the number of hits
+     */
+    long getTotalAccessCount();
+
+    /**
+     * Get the number of cache misses.
+     * 
+     * @return the number of misses
+     */
+    long getMissCount();
+
+    /**
+     * Reset the cache miss counter.
+     */
+    void resetMissCount();
+
+    /**
+     * Get the number of elements/objects in the cache.
+     * @return the number of elements
+     */
+    long getElementCount();
+
+    /**
      * Add a listener to this cache that is informed after a number of accesses.
      */
     void setAccessListener(CacheAccessListener listener);
 
+    /**
+     * Gathers the stats of the cache for logging.
+     */
+    String getCacheInfoAsString();
+
 }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/CacheAccessListener.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/CacheAccessListener.java?rev=1182713&r1=1182712&r2=1182713&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/CacheAccessListener.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/CacheAccessListener.java Thu Oct 13 08:28:43 2011
@@ -28,9 +28,10 @@ public interface CacheAccessListener {
     int ACCESS_INTERVAL = 127;
 
     /**
-     * The cache calls this method after a number of accessed.
+     * The cache calls this method after a number of accessed.<br>
+     * For statistical purposes, the cache access count is included
      */
-    void cacheAccessed();
+    void cacheAccessed(long accessCount);
 
     /**
      * Called after the cache is no longer used.

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/CacheManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/CacheManager.java?rev=1182713&r1=1182712&r2=1182713&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/CacheManager.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/CacheManager.java Thu Oct 13 08:28:43 2011
@@ -17,6 +17,7 @@
 package org.apache.jackrabbit.core.cache;
 
 import java.util.ArrayList;
+import java.util.List;
 import java.util.WeakHashMap;
 
 import org.slf4j.Logger;
@@ -54,6 +55,9 @@ public class CacheManager implements Cac
     /** The default minimum resize interval (in ms). */
     private static final int DEFAULT_MIN_RESIZE_INTERVAL = 1000;
 
+    /** The default minimum stats logging interval (in ms). */
+    private static final int DEFAULT_LOG_STATS_INTERVAL = 60 * 1000;
+
     /** The size of a big object, to detect if a cache is full or not. */
     private static final int BIG_OBJECT_SIZE = 16 * 1024;
 
@@ -77,11 +81,21 @@ public class CacheManager implements Cac
             "org.apache.jackrabbit.cacheResizeInterval",
             DEFAULT_MIN_RESIZE_INTERVAL);
 
-        /** The last time the caches where resized. */
+    /** The minimum interval time between stats are logged */
+    private long minLogStatsInterval = Long.getLong(
+            "org.apache.jackrabbit.cacheLogStatsInterval",
+            DEFAULT_LOG_STATS_INTERVAL);
+
+    /** The last time the caches where resized. */
     private volatile long nextResize =
         System.currentTimeMillis() + DEFAULT_MIN_RESIZE_INTERVAL;
 
 
+    /** The last time the cache stats were logged. */
+    private volatile long nextLogStats =
+            System.currentTimeMillis() + DEFAULT_LOG_STATS_INTERVAL;
+
+
     public long getMaxMemory() {
         return maxMemory;
     }
@@ -118,7 +132,10 @@ public class CacheManager implements Cac
      * After one of the caches is accessed a number of times, this method is called.
      * Resize the caches if required.
      */
-    public void cacheAccessed() {
+    public void cacheAccessed(long accessCount) {
+
+        logCacheStats();
+
         long now = System.currentTimeMillis();
         if (now < nextResize) {
             return;
@@ -136,7 +153,22 @@ public class CacheManager implements Cac
     }
 
     /**
-     * Re-calcualte the maximum memory for each cache, and set the new limits.
+     * Log info about the caches.
+     */
+    private void logCacheStats() {
+        if (log.isDebugEnabled()) {
+            long now = System.currentTimeMillis();
+            if (now < nextLogStats) {
+                return;
+            }
+            for (Cache cache : caches.keySet()) {
+                log.debug(cache.getCacheInfoAsString());
+            }
+            nextLogStats = now + minLogStatsInterval;
+        }
+    }
+    /**
+     * Re-calculate the maximum memory for each cache, and set the new limits.
      */
     private void resizeAll() {
         if (log.isDebugEnabled()) {
@@ -146,11 +178,9 @@ public class CacheManager implements Cac
         // entries in a weak hash map may disappear any time
         // so can't use size() / keySet() directly
         // only using the iterator guarantees that we don't get null references
-        ArrayList<Cache> list = new ArrayList<Cache>();
+        List<Cache> list = new ArrayList<Cache>();
         synchronized (caches) {
-            for (Cache c: caches.keySet()) {
-                list.add(c);
-            }
+            list.addAll(caches.keySet());
         }
         if (list.size() == 0) {
             // nothing to do

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/ConcurrentCache.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/ConcurrentCache.java?rev=1182713&r1=1182712&r2=1182713&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/ConcurrentCache.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/ConcurrentCache.java Thu Oct 13 08:28:43 2011
@@ -57,10 +57,12 @@ public class ConcurrentCache<K, V> exten
 
     }
 
+    private final String name;
     private final Map<K, E<V>>[] segments;
 
     @SuppressWarnings({ "unchecked", "serial" })
-    public ConcurrentCache(int numberOfSegments) {
+    public ConcurrentCache(String name, int numberOfSegments) {
+        this.name = name;
         this.segments = new Map[numberOfSegments];
         for (int i = 0; i < segments.length; i++) {
             segments[i] = new LinkedHashMap<K, E<V>>(16, 0.75f, true) {
@@ -77,8 +79,8 @@ public class ConcurrentCache<K, V> exten
         }
     }
 
-    public ConcurrentCache() {
-        this(DEFAULT_NUMBER_OF_SEGMENTS);
+    public ConcurrentCache(String name) {
+        this(name, DEFAULT_NUMBER_OF_SEGMENTS);
     }
 
     /**
@@ -124,10 +126,10 @@ public class ConcurrentCache<K, V> exten
             E<V> entry = segment.get(key);
             if (entry != null) {
                 return entry.value;
-            } else {
-                return null;
             }
         }
+        recordCacheMiss();
+        return null;
     }
 
     /**
@@ -252,4 +254,17 @@ public class ConcurrentCache<K, V> exten
         }
     }
 
+    public long getElementCount() {
+        long count = 0;
+        for (int i = 0; i < segments.length; i++) {
+            count += segments[i].size();
+        }
+        return count;
+    }
+
+    @Override
+    public String toString() {
+        return name + "[" + getClass().getSimpleName() + "@"
+                + Integer.toHexString(hashCode()) + "]";
+    }
 }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java?rev=1182713&r1=1182712&r2=1182713&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java Thu Oct 13 08:28:43 2011
@@ -377,7 +377,7 @@ public abstract class AbstractBundlePers
     public void init(PMContext context) throws Exception {
         this.context = context;
         // init bundle cache
-        bundles = new ConcurrentCache<NodeId, NodePropBundle>();
+        bundles = new ConcurrentCache<NodeId, NodePropBundle>(context.getHomeDir().getName() + "BundleCache");
         bundles.setMaxMemorySize(bundleCacheSize);
     }
 

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/MLRUItemStateCache.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/MLRUItemStateCache.java?rev=1182713&r1=1182712&r2=1182713&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/MLRUItemStateCache.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/MLRUItemStateCache.java Thu Oct 13 08:28:43 2011
@@ -45,7 +45,7 @@ public class MLRUItemStateCache implemen
     private volatile long numWrites = 0;
 
     private final ConcurrentCache<ItemId, ItemState> cache =
-        new ConcurrentCache<ItemId, ItemState>();
+        new ConcurrentCache<ItemId, ItemState>(MLRUItemStateCache.class.getSimpleName());
 
     public MLRUItemStateCache(CacheManager cacheMgr) {
         cache.setMaxMemorySize(DEFAULT_MAX_MEM);

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/cache/ConcurrentCacheTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/cache/ConcurrentCacheTest.java?rev=1182713&r1=1182712&r2=1182713&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/cache/ConcurrentCacheTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/cache/ConcurrentCacheTest.java Thu Oct 13 08:28:43 2011
@@ -37,7 +37,7 @@ public class ConcurrentCacheTest extends
         }
 
         ConcurrentCache<NodeId, NodeId> cache =
-            new ConcurrentCache<NodeId, NodeId>();
+            new ConcurrentCache<NodeId, NodeId>("test");
         cache.setMaxMemorySize(ids.length / 2);
 
         for (int i = 0; i < ids.length; i++) {