]> source.dussan.org Git - jgit.git/commitdiff
DHT: Use a proper HashMap for RecentChunk lookups 07/3707/1
authorShawn O. Pearce <spearce@spearce.org>
Fri, 10 Jun 2011 00:59:22 +0000 (17:59 -0700)
committerShawn O. Pearce <spearce@spearce.org>
Fri, 10 Jun 2011 00:59:22 +0000 (17:59 -0700)
A linear search is somewhat acceptable for only 4 recent chunks, but
a HashMap based lookup would be better. The table will have 16 slots
by default and given the hashCode() of ChunkKey is derived from the
SHA-1 of the chunk, each chunk will fall into its own bucket within
the table and thus evaluate only 1 entry during lookup instead of 4.

Some users may also want to devote more memory to the recent chunks,
in which case expanding this list to a longer length will help to
reduce chunk faults, but would increase search time. Using a HashMap
will help this code to scale to larger sizes better.

Change-Id: Ia41b7a1cc69ad27b85749e3b74cbf8d0aa338044
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/RecentChunks.java

index f75e3bdc8216c654b7fbc22a73ffa861cf3f198a..095de43fe7215f50d1d076452dd2f522c474541d 100644 (file)
@@ -44,6 +44,7 @@
 package org.eclipse.jgit.storage.dht;
 
 import java.io.IOException;
+import java.util.HashMap;
 
 import org.eclipse.jgit.lib.AnyObjectId;
 import org.eclipse.jgit.lib.ObjectLoader;
@@ -57,6 +58,8 @@ final class RecentChunks {
 
        private final int maxSize;
 
+       private final HashMap<ChunkKey, Node> byKey;
+
        private int curSize;
 
        private Node lruHead;
@@ -67,36 +70,36 @@ final class RecentChunks {
                this.reader = reader;
                this.stats = reader.getStatistics();
                this.maxSize = reader.getOptions().getRecentChunkCacheSize();
+               this.byKey = new HashMap<ChunkKey, Node>();
        }
 
        PackChunk get(ChunkKey key) {
-               for (Node n = lruHead; n != null; n = n.next) {
-                       if (key.equals(n.chunk.getChunkKey())) {
-                               hit(n);
-                               stats.recentChunks_Hits++;
-                               return n.chunk;
-                       }
+               Node n = byKey.get(key);
+               if (n != null) {
+                       hit(n);
+                       stats.recentChunks_Hits++;
+                       return n.chunk;
                }
                stats.recentChunks_Miss++;
                return null;
        }
 
        void put(PackChunk chunk) {
-               for (Node n = lruHead; n != null; n = n.next) {
-                       if (n.chunk == chunk) {
-                               hit(n);
-                               return;
-                       }
+               Node n = byKey.get(chunk.getChunkKey());
+               if (n != null && n.chunk == chunk) {
+                       hit(n);
+                       return;
                }
 
-               Node n;
                if (curSize < maxSize) {
                        n = new Node();
                        curSize++;
                } else {
                        n = lruTail;
+                       byKey.remove(n.chunk.getChunkKey());
                }
                n.chunk = chunk;
+               byKey.put(chunk.getChunkKey(), n);
                hit(n);
        }
 
@@ -167,6 +170,7 @@ final class RecentChunks {
                curSize = 0;
                lruHead = null;
                lruTail = null;
+               byKey.clear();
        }
 
        private void hit(Node n) {