You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by md...@apache.org on 2016/10/19 08:37:19 UTC

svn commit: r1765554 - in /jackrabbit/oak/trunk/oak-segment-tar/src: main/java/org/apache/jackrabbit/oak/segment/SegmentCache.java main/java/org/apache/jackrabbit/oak/segment/SegmentId.java test/java/org/apache/jackrabbit/oak/segment/SegmentCacheTest.java

Author: mduerig
Date: Wed Oct 19 08:37:18 2016
New Revision: 1765554

URL: http://svn.apache.org/viewvc?rev=1765554&view=rev
Log:
OAK-4936: Too many segment cache misses
Replace LIRS cache with Guava cache

(cherry picked from commit a017357)

Modified:
    jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentCache.java
    jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentId.java
    jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/SegmentCacheTest.java

Modified: jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentCache.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentCache.java?rev=1765554&r1=1765553&r2=1765554&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentCache.java (original)
+++ jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentCache.java Wed Oct 19 08:37:18 2016
@@ -24,10 +24,11 @@ import java.util.concurrent.ExecutionExc
 
 import javax.annotation.Nonnull;
 
-import com.google.common.cache.RemovalCause;
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.RemovalListener;
+import com.google.common.cache.RemovalNotification;
 import com.google.common.cache.Weigher;
-import org.apache.jackrabbit.oak.cache.CacheLIRS;
-import org.apache.jackrabbit.oak.cache.CacheLIRS.EvictionCallback;
 import org.apache.jackrabbit.oak.cache.CacheStats;
 
 /**
@@ -41,42 +42,46 @@ import org.apache.jackrabbit.oak.cache.C
  * As a consequence this cache is actually only queried for segments it does not contain,
  * which are then loaded through the loader passed to {@link #getSegment(SegmentId, Callable)}.
  * This behaviour is eventually reflected in the cache statistics (see {@link #getCacheStats()}),
- * which always reports a {@link CacheStats#getMissRate() miss rate} of 1.
+ * which always reports a {@link CacheStats#getHitRate()} () miss rate} of 1.
  */
 public class SegmentCache {
     public static final int DEFAULT_SEGMENT_CACHE_MB = 256;
 
     private final Weigher<SegmentId, Segment> weigher = new Weigher<SegmentId, Segment>() {
         @Override
-        public int weigh(SegmentId id, Segment segment) {
+        public int weigh(@Nonnull SegmentId id, @Nonnull Segment segment) {
             return 224 + segment.size();
         }
     };
 
+    private final long maximumWeight;
+
     /**
      * Cache of recently accessed segments
      */
     @Nonnull
-    private final CacheLIRS<SegmentId, Segment> cache;
+    private final Cache<SegmentId, Segment> cache;
 
     /**
      * Create a new segment cache of the given size.
      * @param cacheSizeMB  size of the cache in megabytes.
      */
     public SegmentCache(long cacheSizeMB) {
-        this.cache = CacheLIRS.<SegmentId, Segment>newBuilder()
-            .module("SegmentCache")
-            .maximumWeight(cacheSizeMB * 1024 * 1024)
-            .averageWeight(Segment.MAX_SEGMENT_SIZE / 2)
-            .weigher(weigher)
-            .evictionCallback(new EvictionCallback<SegmentId, Segment>() {
-                @Override
-                public void evicted(SegmentId id, Segment segment, RemovalCause cause) {
-                    if (segment != null) {
-                        id.unloaded();
+        this.maximumWeight = cacheSizeMB * 1024 * 1024;
+        this.cache = CacheBuilder.newBuilder()
+                .concurrencyLevel(16)
+                .recordStats()
+                .maximumWeight(maximumWeight)
+                .weigher(weigher)
+                .removalListener(new RemovalListener<SegmentId, Segment>() {
+                    @Override
+                    public void onRemoval(@Nonnull RemovalNotification<SegmentId, Segment> notification) {
+                        SegmentId id = notification.getKey();
+                        if (id != null) {
+                            id.unloaded();
+                        }
                     }
-                } })
-            .build();
+                }).build();
     }
 
     /**
@@ -87,9 +92,16 @@ public class SegmentCache {
      * @throws ExecutionException  when {@code loader} failed to load an segment
      */
     @Nonnull
-    public Segment getSegment(@Nonnull SegmentId id, @Nonnull Callable<Segment> loader)
+    public Segment getSegment(@Nonnull final SegmentId id, @Nonnull final Callable<Segment> loader)
     throws ExecutionException {
-        return cache.get(id, loader);
+        try {
+            Segment segment = loader.call();
+            cache.put(id, segment);
+            id.loaded(segment);
+            return segment;
+        } catch (Exception e) {
+            throw new ExecutionException(e);
+        }
     }
 
     /**
@@ -97,8 +109,9 @@ public class SegmentCache {
      * @param segment  the segment to cache
      */
     public void putSegment(@Nonnull Segment segment) {
-        cache.put(segment.getSegmentId(), segment);
-        segment.getSegmentId().loaded(segment);
+        SegmentId segmentId = segment.getSegmentId();
+        cache.put(segmentId, segment);
+        segmentId.loaded(segment);
     }
 
     /**
@@ -114,6 +127,6 @@ public class SegmentCache {
      */
     @Nonnull
     public CacheStats getCacheStats() {
-        return new CacheStats(cache, "Segment Cache", weigher, cache.getMaxMemory());
+        return new CacheStats(cache, "Segment Cache", weigher, maximumWeight);
     }
 }
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentId.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentId.java?rev=1765554&r1=1765553&r2=1765554&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentId.java (original)
+++ jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentId.java Wed Oct 19 08:37:18 2016
@@ -121,8 +121,6 @@ public class SegmentId implements Compar
                     try {
                         log.debug("Loading segment {}", this);
                         segment = store.readSegment(this);
-                        gcGeneration = segment.getGcGeneration();
-                        this.segment = segment;
                     } catch (SegmentNotFoundException snfe) {
                         log.error("Segment not found: {}. {}", this, gcInfo(), snfe);
                         throw snfe;

Modified: jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/SegmentCacheTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/SegmentCacheTest.java?rev=1765554&r1=1765553&r2=1765554&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/SegmentCacheTest.java (original)
+++ jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/SegmentCacheTest.java Wed Oct 19 08:37:18 2016
@@ -83,25 +83,25 @@ public class SegmentCacheTest {
         // load
         cache.getSegment(id, loader);
         assertEquals(1, stats.getElementCount());
-        assertEquals(1, stats.getLoadCount());
+        assertEquals(0, stats.getLoadCount());
         assertEquals(0, stats.getHitCount());
-        assertEquals(1, stats.getMissCount());
-        assertEquals(1, stats.getRequestCount());
+        assertEquals(0, stats.getMissCount());
+        assertEquals(0, stats.getRequestCount());
 
         // cache hit
         cache.getSegment(id, loader);
         assertEquals(1, stats.getElementCount());
-        assertEquals(1, stats.getLoadCount());
-        assertEquals(1, stats.getHitCount());
-        assertEquals(1, stats.getMissCount());
-        assertEquals(2, stats.getRequestCount());
+        assertEquals(0, stats.getLoadCount());
+        assertEquals(0, stats.getHitCount());
+        assertEquals(0, stats.getMissCount());
+        assertEquals(0, stats.getRequestCount());
 
         cache.clear();
         assertEquals(0, stats.getElementCount());
-        assertEquals(1, stats.getLoadCount());
-        assertEquals(1, stats.getHitCount());
-        assertEquals(1, stats.getMissCount());
-        assertEquals(2, stats.getRequestCount());
+        assertEquals(0, stats.getLoadCount());
+        assertEquals(0, stats.getHitCount());
+        assertEquals(0, stats.getMissCount());
+        assertEquals(0, stats.getRequestCount());
 
         stats.resetStats();
         assertEquals(0, stats.getElementCount());