瀏覽代碼

ZOOKEEPER-4919: Make ResponseCache a LRU as it supposed to be

Reviewers: tisonkun, kezhuw
Author: mikkosc
Closes #2243 from mikkosc/fix-lru-cache
mikkosc 2 周之前
父節點
當前提交
db8fe9c241

+ 10 - 8
zookeeper-server/src/main/java/org/apache/zookeeper/server/ResponseCache.java

@@ -33,8 +33,13 @@ public class ResponseCache {
     public static final int DEFAULT_RESPONSE_CACHE_SIZE = 400;
     public static final int DEFAULT_RESPONSE_CACHE_SIZE = 400;
     private final int cacheSize;
     private final int cacheSize;
     private static class Entry {
     private static class Entry {
-        public Stat stat;
-        public byte[] data;
+        public final Stat stat;
+        public final byte[] data;
+
+        Entry(Stat stat, byte[] data) {
+            this.stat = stat;
+            this.data = data;
+        }
     }
     }
 
 
     private final Map<String, Entry> cache;
     private final Map<String, Entry> cache;
@@ -50,10 +55,7 @@ public class ResponseCache {
     }
     }
 
 
     public void put(String path, byte[] data, Stat stat) {
     public void put(String path, byte[] data, Stat stat) {
-        Entry entry = new Entry();
-        entry.data = data;
-        entry.stat = stat;
-        cache.put(path, entry);
+        cache.put(path, new Entry(stat, data));
     }
     }
 
 
     public byte[] get(String key, Stat stat) {
     public byte[] get(String key, Stat stat) {
@@ -76,10 +78,10 @@ public class ResponseCache {
 
 
     private static class LRUCache<K, V> extends LinkedHashMap<K, V> {
     private static class LRUCache<K, V> extends LinkedHashMap<K, V> {
 
 
-        private int cacheSize;
+        private final int cacheSize;
 
 
         LRUCache(int cacheSize) {
         LRUCache(int cacheSize) {
-            super(cacheSize / 4);
+            super(cacheSize / 4, 0.75f, true);
             this.cacheSize = cacheSize;
             this.cacheSize = cacheSize;
         }
         }
 
 

+ 0 - 0
zookeeper-server/src/test/java/org/apache/zookeeper/server/FollowerRequestProcessorTest.java → zookeeper-server/src/test/java/org/apache/zookeeper/server/quorum/FollowerRequestProcessorTest.java


+ 22 - 2
zookeeper-server/src/test/java/org/apache/zookeeper/test/ResponseCacheTest.java

@@ -79,6 +79,7 @@ public class ResponseCacheTest extends ClientBase {
         Stat writeStat = new Stat();
         Stat writeStat = new Stat();
         Stat readStat = new Stat();
         Stat readStat = new Stat();
         byte[] readData = null;
         byte[] readData = null;
+        int cacheSize = Integer.getInteger(ZooKeeperServer.GET_DATA_RESPONSE_CACHE_SIZE);
         int reads = 10;
         int reads = 10;
         long expectedHits = 0;
         long expectedHits = 0;
         long expectedMisses = 0;
         long expectedMisses = 0;
@@ -88,7 +89,7 @@ public class ResponseCacheTest extends ClientBase {
         LOG.info("caching: {}", useCache);
         LOG.info("caching: {}", useCache);
 
 
         if (useCache) {
         if (useCache) {
-            assertEquals(zks.getReadResponseCache().getCacheSize(), 32);
+            assertEquals(zks.getReadResponseCache().getCacheSize(), cacheSize);
             assertEquals(zks.getGetChildrenResponseCache().getCacheSize(), 64);
             assertEquals(zks.getGetChildrenResponseCache().getCacheSize(), 64);
         }
         }
 
 
@@ -146,15 +147,21 @@ public class ResponseCacheTest extends ClientBase {
         createPath(path + "/a/b/e/g", zk);
         createPath(path + "/a/b/e/g", zk);
         createPath(path + "/a/b/e/h", zk);
         createPath(path + "/a/b/e/h", zk);
 
 
+        createPath(path + "/x", zk);
+        for (int i = 0; i < cacheSize * 2; ++i) {
+            createPath(path + "/x/y" + i, zk);
+        }
+
         checkPath(path + "/a", zk, 2);
         checkPath(path + "/a", zk, 2);
         checkPath(path + "/a/b", zk, 2);
         checkPath(path + "/a/b", zk, 2);
         checkPath(path + "/a/c", zk, 0);
         checkPath(path + "/a/c", zk, 0);
         checkPath(path + "/a/b/d", zk, 0);
         checkPath(path + "/a/b/d", zk, 0);
         checkPath(path + "/a/b/e", zk, 3);
         checkPath(path + "/a/b/e", zk, 3);
         checkPath(path + "/a/b/e/h", zk, 0);
         checkPath(path + "/a/b/e/h", zk, 0);
+        checkPath(path + "/x", zk, cacheSize * 2);
 
 
         if (useCache) {
         if (useCache) {
-            expectedMisses += 6;
+            expectedMisses += 7;
         }
         }
 
 
         checkCacheStatus(expectedHits, expectedMisses, "response_packet_get_children_cache_hits",
         checkCacheStatus(expectedHits, expectedMisses, "response_packet_get_children_cache_hits",
@@ -170,6 +177,19 @@ public class ResponseCacheTest extends ClientBase {
 
 
         checkCacheStatus(expectedHits, expectedMisses, "response_packet_get_children_cache_hits",
         checkCacheStatus(expectedHits, expectedMisses, "response_packet_get_children_cache_hits",
                 "response_packet_get_children_cache_misses");
                 "response_packet_get_children_cache_misses");
+
+        for (int i = 0; i < cacheSize * 2; ++i) {
+            checkPath(path + "/a", zk, 2);
+            checkPath(path + "/x/y" + i, zk, 0);
+
+            if (useCache) {
+                expectedHits += 1;
+                expectedMisses += 1;
+            }
+
+            checkCacheStatus(expectedHits, expectedMisses, "response_packet_get_children_cache_hits",
+                    "response_packet_get_children_cache_misses");
+        }
     }
     }
 
 
     private void createPath(String path, ZooKeeper zk) throws Exception {
     private void createPath(String path, ZooKeeper zk) throws Exception {