From 1e6b02643c7052a385dba041ffa7c7fd8b8a3ac8 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Thu, 9 Jun 2011 17:59:22 -0700 Subject: [PATCH] DHT: Use a proper HashMap for RecentChunk lookups 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 --- .../jgit/storage/dht/RecentChunks.java | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/RecentChunks.java b/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/RecentChunks.java index f75e3bdc8..095de43fe 100644 --- a/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/RecentChunks.java +++ b/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/RecentChunks.java @@ -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 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(); } 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) {