summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn O. Pearce <spearce@spearce.org>2011-08-14 18:51:58 -0400
committerCode Review <codereview-daemon@eclipse.org>2011-08-14 18:51:58 -0400
commitf820bf34ec4cdc484f53a811173fc31b7139b998 (patch)
tree5e48a641290a2d9a37ac49aaef44f335a0df2a2a
parent2610eaf386f37386e9886a8635d499ebf772a240 (diff)
parentd34ec1201950c01f9b6a104540b31dbd614eea65 (diff)
downloadjgit-f820bf34ec4cdc484f53a811173fc31b7139b998.tar.gz
jgit-f820bf34ec4cdc484f53a811173fc31b7139b998.zip
Merge changes I1ca7acb4,Ia41b7a1c,I33b65286,Ie2823724,I6b65bfb4
* changes: DHT: Change DhtReadher caches to be dynamic by workload DHT: Use a proper HashMap for RecentChunk lookups DHT: Always have at least one recent chunk in DhtReader DHT: Fix NPE during prefetch DHT: Drop leading hash digits from row keys
-rw-r--r--org.eclipse.jgit.storage.dht.test/tst/org/eclipse/jgit/storage/dht/ChunkKeyTest.java9
-rw-r--r--org.eclipse.jgit.storage.dht.test/tst/org/eclipse/jgit/storage/dht/ObjectIndexKeyTest.java6
-rw-r--r--org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/ChunkKey.java16
-rw-r--r--org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/DhtCachedPack.java15
-rw-r--r--org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/DhtReader.java18
-rw-r--r--org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/DhtReaderOptions.java121
-rw-r--r--org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/ObjectIndexKey.java16
-rw-r--r--org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/OpenQueue.java10
-rw-r--r--org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/PackChunk.java2
-rw-r--r--org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/Prefetcher.java4
-rw-r--r--org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/RecentChunks.java68
11 files changed, 193 insertions, 92 deletions
diff --git a/org.eclipse.jgit.storage.dht.test/tst/org/eclipse/jgit/storage/dht/ChunkKeyTest.java b/org.eclipse.jgit.storage.dht.test/tst/org/eclipse/jgit/storage/dht/ChunkKeyTest.java
index 63cbf520c0..9219663667 100644
--- a/org.eclipse.jgit.storage.dht.test/tst/org/eclipse/jgit/storage/dht/ChunkKeyTest.java
+++ b/org.eclipse.jgit.storage.dht.test/tst/org/eclipse/jgit/storage/dht/ChunkKeyTest.java
@@ -43,7 +43,8 @@
package org.eclipse.jgit.storage.dht;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import org.eclipse.jgit.lib.ObjectId;
import org.junit.Test;
@@ -59,19 +60,19 @@ public class ChunkKeyTest {
ChunkKey key1 = ChunkKey.create(repo1, id);
assertEquals(repo1.asInt(), key1.getRepositoryId());
assertEquals(id, key1.getChunkHash());
- assertEquals("3e.41234567.3e64b928d51b3a28e89cfe2a3f0eeae35ef07839",
+ assertEquals("41234567.3e64b928d51b3a28e89cfe2a3f0eeae35ef07839",
key1.asString());
ChunkKey key2 = ChunkKey.fromBytes(key1.asBytes());
assertEquals(repo1.asInt(), key2.getRepositoryId());
assertEquals(id, key2.getChunkHash());
- assertEquals("3e.41234567.3e64b928d51b3a28e89cfe2a3f0eeae35ef07839",
+ assertEquals("41234567.3e64b928d51b3a28e89cfe2a3f0eeae35ef07839",
key2.asString());
ChunkKey key3 = ChunkKey.fromString(key1.asString());
assertEquals(repo1.asInt(), key3.getRepositoryId());
assertEquals(id, key3.getChunkHash());
- assertEquals("3e.41234567.3e64b928d51b3a28e89cfe2a3f0eeae35ef07839",
+ assertEquals("41234567.3e64b928d51b3a28e89cfe2a3f0eeae35ef07839",
key3.asString());
assertEquals(key1, key2);
diff --git a/org.eclipse.jgit.storage.dht.test/tst/org/eclipse/jgit/storage/dht/ObjectIndexKeyTest.java b/org.eclipse.jgit.storage.dht.test/tst/org/eclipse/jgit/storage/dht/ObjectIndexKeyTest.java
index ab3b423ede..d3419bd140 100644
--- a/org.eclipse.jgit.storage.dht.test/tst/org/eclipse/jgit/storage/dht/ObjectIndexKeyTest.java
+++ b/org.eclipse.jgit.storage.dht.test/tst/org/eclipse/jgit/storage/dht/ObjectIndexKeyTest.java
@@ -58,19 +58,19 @@ public class ObjectIndexKeyTest {
ObjectIndexKey key1 = ObjectIndexKey.create(repo, id);
assertEquals(repo.asInt(), key1.getRepositoryId());
assertEquals(key1, id);
- assertEquals("3e.41234567.3e64b928d51b3a28e89cfe2a3f0eeae35ef07839",
+ assertEquals("41234567.3e64b928d51b3a28e89cfe2a3f0eeae35ef07839",
key1.asString());
ObjectIndexKey key2 = ObjectIndexKey.fromBytes(key1.asBytes());
assertEquals(repo.asInt(), key2.getRepositoryId());
assertEquals(key2, id);
- assertEquals("3e.41234567.3e64b928d51b3a28e89cfe2a3f0eeae35ef07839",
+ assertEquals("41234567.3e64b928d51b3a28e89cfe2a3f0eeae35ef07839",
key2.asString());
ObjectIndexKey key3 = ObjectIndexKey.fromString(key1.asString());
assertEquals(repo.asInt(), key3.getRepositoryId());
assertEquals(key3, id);
- assertEquals("3e.41234567.3e64b928d51b3a28e89cfe2a3f0eeae35ef07839",
+ assertEquals("41234567.3e64b928d51b3a28e89cfe2a3f0eeae35ef07839",
key3.asString());
}
}
diff --git a/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/ChunkKey.java b/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/ChunkKey.java
index 272b5ea173..11a151f6ba 100644
--- a/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/ChunkKey.java
+++ b/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/ChunkKey.java
@@ -54,7 +54,7 @@ import org.eclipse.jgit.lib.ObjectId;
/** Unique identifier of a {@link PackChunk} in the DHT. */
public final class ChunkKey implements RowKey {
- static final int KEYLEN = 52;
+ static final int KEYLEN = 49;
/**
* @param repo
@@ -84,8 +84,8 @@ public final class ChunkKey implements RowKey {
throw new IllegalArgumentException(MessageFormat.format(
DhtText.get().invalidChunkKey, decode(key, ptr, ptr + len)));
- int repo = parse32(key, ptr + 3);
- ObjectId chunk = ObjectId.fromString(key, ptr + 12);
+ int repo = parse32(key, ptr);
+ ObjectId chunk = ObjectId.fromString(key, ptr + 9);
return new ChunkKey(repo, chunk);
}
@@ -122,13 +122,9 @@ public final class ChunkKey implements RowKey {
public byte[] asBytes() {
byte[] r = new byte[KEYLEN];
- chunk.copyTo(r, 12);
- format32(r, 3, repo);
- // bucket is the leading 2 digits of the SHA-1.
- r[11] = '.';
- r[2] = '.';
- r[1] = r[12 + 1];
- r[0] = r[12 + 0];
+ format32(r, 0, repo);
+ r[8] = '.';
+ chunk.copyTo(r, 9);
return r;
}
diff --git a/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/DhtCachedPack.java b/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/DhtCachedPack.java
index 39a76463fb..0fd253bfbf 100644
--- a/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/DhtCachedPack.java
+++ b/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/DhtCachedPack.java
@@ -125,9 +125,18 @@ public class DhtCachedPack extends CachedPack {
throws IOException {
if (keyList == null)
init();
- Prefetcher p = new Prefetcher(ctx, 0);
- p.push(Arrays.asList(keyList));
- copyPack(out, p, validate);
+
+ // Clear the recent chunks because all of the reader's
+ // chunk limit should be made available for prefetch.
+ int cacheLimit = ctx.getOptions().getChunkLimit();
+ ctx.getRecentChunks().setMaxBytes(0);
+ try {
+ Prefetcher p = new Prefetcher(ctx, 0, cacheLimit);
+ p.push(Arrays.asList(keyList));
+ copyPack(out, p, validate);
+ } finally {
+ ctx.getRecentChunks().setMaxBytes(cacheLimit);
+ }
}
private void copyPack(PackOutputStream out, Prefetcher prefetcher,
diff --git a/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/DhtReader.java b/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/DhtReader.java
index f9288b9e2e..330b5c0734 100644
--- a/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/DhtReader.java
+++ b/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/DhtReader.java
@@ -156,6 +156,10 @@ public class DhtReader extends ObjectReader implements ObjectReuseAsIs {
return recentInfo;
}
+ RecentChunks getRecentChunks() {
+ return recentChunks;
+ }
+
DeltaBaseCache getDeltaBaseCache() {
return deltaBaseCache;
}
@@ -242,7 +246,7 @@ public class DhtReader extends ObjectReader implements ObjectReuseAsIs {
// configured as push might invoke our own methods that may
// try to call back into the active prefetcher.
//
- Prefetcher p = new Prefetcher(this, OBJ_COMMIT);
+ Prefetcher p = prefetch(OBJ_COMMIT, readerOptions.getWalkCommitsPrefetchRatio());
p.push(this, roots);
prefetcher = p;
}
@@ -256,7 +260,7 @@ public class DhtReader extends ObjectReader implements ObjectReuseAsIs {
// configured as push might invoke our own methods that may
// try to call back into the active prefetcher.
//
- Prefetcher p = new Prefetcher(this, OBJ_TREE);
+ Prefetcher p = prefetch(OBJ_TREE, readerOptions.getWalkTreesPrefetchRatio());
p.push(this, min.getTree(), max.getTree());
prefetcher = p;
}
@@ -391,14 +395,22 @@ public class DhtReader extends ObjectReader implements ObjectReuseAsIs {
new RepresentationSelector(packer, this, monitor).select(itr);
}
+ private Prefetcher prefetch(final int type, final int ratio) {
+ int limit = readerOptions.getChunkLimit();
+ int prefetchLimit = (int) (limit * (ratio / 100.0));
+ recentChunks.setMaxBytes(limit - prefetchLimit);
+ return new Prefetcher(this, type, prefetchLimit);
+ }
+
private void endPrefetch() {
+ recentChunks.setMaxBytes(getOptions().getChunkLimit());
prefetcher = null;
}
@SuppressWarnings("unchecked")
public void writeObjects(PackOutputStream out, List<ObjectToPack> objects)
throws IOException {
- prefetcher = new Prefetcher(this, 0);
+ prefetcher = prefetch(0, readerOptions.getWriteObjectsPrefetchRatio());
try {
List itr = objects;
new ObjectWriter(this, prefetcher).plan(itr);
diff --git a/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/DhtReaderOptions.java b/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/DhtReaderOptions.java
index 0890e39ad0..db3f51028f 100644
--- a/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/DhtReaderOptions.java
+++ b/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/DhtReaderOptions.java
@@ -57,7 +57,15 @@ public class DhtReaderOptions {
private boolean prefetchFollowEdgeHints;
- private int prefetchLimit;
+ private int chunkLimit;
+
+ private int openQueuePrefetchRatio;
+
+ private int walkCommitsPrefetchRatio;
+
+ private int walkTreesPrefetchRatio;
+
+ private int writeObjectsPrefetchRatio;
private int objectIndexConcurrentBatches;
@@ -69,15 +77,18 @@ public class DhtReaderOptions {
private int recentInfoCacheSize;
- private int recentChunkCacheSize;
-
private boolean trackFirstChunkLoad;
/** Create a default reader configuration. */
public DhtReaderOptions() {
setTimeout(Timeout.seconds(5));
setPrefetchFollowEdgeHints(true);
- setPrefetchLimit(5 * MiB);
+
+ setChunkLimit(5 * MiB);
+ setOpenQueuePrefetchRatio(20 /* percent */);
+ setWalkCommitsPrefetchRatio(20 /* percent */);
+ setWalkTreesPrefetchRatio(20 /* percent */);
+ setWriteObjectsPrefetchRatio(90 /* percent */);
setObjectIndexConcurrentBatches(2);
setObjectIndexBatchSize(512);
@@ -86,7 +97,6 @@ public class DhtReaderOptions {
setDeltaBaseCacheLimit(10 * MiB);
setRecentInfoCacheSize(4096);
- setRecentChunkCacheSize(4);
}
/** @return default timeout to wait on long operations before aborting. */
@@ -125,19 +135,83 @@ public class DhtReaderOptions {
return this;
}
- /** @return number of bytes to load during prefetching. */
- public int getPrefetchLimit() {
- return prefetchLimit;
+ /** @return number of bytes to hold within a DhtReader. */
+ public int getChunkLimit() {
+ return chunkLimit;
}
/**
- * Set the number of bytes the prefetcher should hold onto.
+ * Set the number of bytes hold within a DhtReader.
*
* @param maxBytes
* @return {@code this}
*/
- public DhtReaderOptions setPrefetchLimit(int maxBytes) {
- prefetchLimit = Math.max(1024, maxBytes);
+ public DhtReaderOptions setChunkLimit(int maxBytes) {
+ chunkLimit = Math.max(1024, maxBytes);
+ return this;
+ }
+
+ /** @return percentage of {@link #getChunkLimit()} used for prefetch, 0..100. */
+ public int getOpenQueuePrefetchRatio() {
+ return openQueuePrefetchRatio;
+ }
+
+ /**
+ * Set the prefetch ratio used by the open object queue.
+ *
+ * @param ratio 0..100.
+ * @return {@code this}
+ */
+ public DhtReaderOptions setOpenQueuePrefetchRatio(int ratio) {
+ openQueuePrefetchRatio = Math.max(0, Math.min(ratio, 100));
+ return this;
+ }
+
+ /** @return percentage of {@link #getChunkLimit()} used for prefetch, 0..100. */
+ public int getWalkCommitsPrefetchRatio() {
+ return walkCommitsPrefetchRatio;
+ }
+
+ /**
+ * Set the prefetch ratio used by the open object queue.
+ *
+ * @param ratio 0..100.
+ * @return {@code this}
+ */
+ public DhtReaderOptions setWalkCommitsPrefetchRatio(int ratio) {
+ walkCommitsPrefetchRatio = Math.max(0, Math.min(ratio, 100));
+ return this;
+ }
+
+ /** @return percentage of {@link #getChunkLimit()} used for prefetch, 0..100. */
+ public int getWalkTreesPrefetchRatio() {
+ return walkTreesPrefetchRatio;
+ }
+
+ /**
+ * Set the prefetch ratio used by the open object queue.
+ *
+ * @param ratio 0..100.
+ * @return {@code this}
+ */
+ public DhtReaderOptions setWalkTreesPrefetchRatio(int ratio) {
+ walkTreesPrefetchRatio = Math.max(0, Math.min(ratio, 100));
+ return this;
+ }
+
+ /** @return percentage of {@link #getChunkLimit()} used for prefetch, 0..100. */
+ public int getWriteObjectsPrefetchRatio() {
+ return writeObjectsPrefetchRatio;
+ }
+
+ /**
+ * Set the prefetch ratio used by the open object queue.
+ *
+ * @param ratio 0..100.
+ * @return {@code this}
+ */
+ public DhtReaderOptions setWriteObjectsPrefetchRatio(int ratio) {
+ writeObjectsPrefetchRatio = Math.max(0, Math.min(ratio, 100));
return this;
}
@@ -226,24 +300,6 @@ public class DhtReaderOptions {
return this;
}
- /** @return number of recent chunks to hold onto per-reader. */
- public int getRecentChunkCacheSize() {
- return recentChunkCacheSize;
- }
-
- /**
- * Set the number of chunks each reader holds onto for recently used access.
- *
- * @param chunkCnt
- * the number of chunks each reader retains of recently used
- * chunks to smooth out access.
- * @return {@code this}
- */
- public DhtReaderOptions setRecentChunkCacheSize(int chunkCnt) {
- recentChunkCacheSize = Math.max(0, chunkCnt);
- return this;
- }
-
/**
* @return true if {@link DhtReader.Statistics} includes the stack trace for
* the first time a chunk is loaded. Supports debugging DHT code.
@@ -277,7 +333,11 @@ public class DhtReaderOptions {
public DhtReaderOptions fromConfig(Config rc) {
setTimeout(Timeout.getTimeout(rc, "core", "dht", "timeout", getTimeout()));
setPrefetchFollowEdgeHints(rc.getBoolean("core", "dht", "prefetchFollowEdgeHints", isPrefetchFollowEdgeHints()));
- setPrefetchLimit(rc.getInt("core", "dht", "prefetchLimit", getPrefetchLimit()));
+ setChunkLimit(rc.getInt("core", "dht", "chunkLimit", getChunkLimit()));
+ setOpenQueuePrefetchRatio(rc.getInt("core", "dht", "openQueuePrefetchRatio", getOpenQueuePrefetchRatio()));
+ setWalkCommitsPrefetchRatio(rc.getInt("core", "dht", "walkCommitsPrefetchRatio", getWalkCommitsPrefetchRatio()));
+ setWalkTreesPrefetchRatio(rc.getInt("core", "dht", "walkTreesPrefetchRatio", getWalkTreesPrefetchRatio()));
+ setWriteObjectsPrefetchRatio(rc.getInt("core", "dht", "writeObjectsPrefetchRatio", getWriteObjectsPrefetchRatio()));
setObjectIndexConcurrentBatches(rc.getInt("core", "dht", "objectIndexConcurrentBatches", getObjectIndexConcurrentBatches()));
setObjectIndexBatchSize(rc.getInt("core", "dht", "objectIndexBatchSize", getObjectIndexBatchSize()));
@@ -286,7 +346,6 @@ public class DhtReaderOptions {
setDeltaBaseCacheLimit(rc.getInt("core", "dht", "deltaBaseCacheLimit", getDeltaBaseCacheLimit()));
setRecentInfoCacheSize(rc.getInt("core", "dht", "recentInfoCacheSize", getRecentInfoCacheSize()));
- setRecentChunkCacheSize(rc.getInt("core", "dht", "recentChunkCacheSize", getRecentChunkCacheSize()));
setTrackFirstChunkLoad(rc.getBoolean("core", "dht", "debugTrackFirstChunkLoad", isTrackFirstChunkLoad()));
return this;
diff --git a/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/ObjectIndexKey.java b/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/ObjectIndexKey.java
index b38fdcec22..ab8f8352b0 100644
--- a/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/ObjectIndexKey.java
+++ b/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/ObjectIndexKey.java
@@ -55,7 +55,7 @@ import org.eclipse.jgit.lib.ObjectId;
/** Identifies an ObjectId in the DHT. */
public final class ObjectIndexKey extends ObjectId implements RowKey {
- private static final int KEYLEN = 52;
+ private static final int KEYLEN = 49;
/**
* @param repo
@@ -75,8 +75,8 @@ public final class ObjectIndexKey extends ObjectId implements RowKey {
throw new IllegalArgumentException(MessageFormat.format(
DhtText.get().invalidChunkKey, decode(key)));
- int repo = parse32(key, 3);
- ObjectId id = ObjectId.fromString(key, 12);
+ int repo = parse32(key, 0);
+ ObjectId id = ObjectId.fromString(key, 9);
return new ObjectIndexKey(repo, id);
}
@@ -106,13 +106,9 @@ public final class ObjectIndexKey extends ObjectId implements RowKey {
public byte[] asBytes() {
byte[] r = new byte[KEYLEN];
- copyTo(r, 12);
- format32(r, 3, repo);
- // bucket is the leading 2 digits of the SHA-1.
- r[11] = '.';
- r[2] = '.';
- r[1] = r[12 + 1];
- r[0] = r[12 + 0];
+ format32(r, 0, repo);
+ r[8] = '.';
+ copyTo(r, 9);
return r;
}
diff --git a/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/OpenQueue.java b/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/OpenQueue.java
index e47f2b2cb4..32b22340d1 100644
--- a/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/OpenQueue.java
+++ b/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/OpenQueue.java
@@ -159,6 +159,7 @@ final class OpenQueue<T extends ObjectId> extends QueueObjectLookup<T>
@Override
public void release() {
+ reader.getRecentChunks().setMaxBytes(reader.getOptions().getChunkLimit());
prefetcher = null;
currChunk = null;
}
@@ -173,8 +174,13 @@ final class OpenQueue<T extends ObjectId> extends QueueObjectLookup<T>
list = new ArrayList<ObjectWithInfo<T>>();
byChunk.put(chunkKey, list);
- if (prefetcher == null)
- prefetcher = new Prefetcher(reader, 0);
+ if (prefetcher == null) {
+ int limit = reader.getOptions().getChunkLimit();
+ int ratio = reader.getOptions().getOpenQueuePrefetchRatio();
+ int prefetchLimit = (int) (limit * (ratio / 100.0));
+ reader.getRecentChunks().setMaxBytes(limit - prefetchLimit);
+ prefetcher = new Prefetcher(reader, 0, prefetchLimit);
+ }
prefetcher.push(chunkKey);
}
list.add(c);
diff --git a/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/PackChunk.java b/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/PackChunk.java
index c0684022f3..66d3d3386b 100644
--- a/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/PackChunk.java
+++ b/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/PackChunk.java
@@ -291,7 +291,7 @@ public final class PackChunk {
}
int findOffset(RepositoryKey repo, AnyObjectId objId) {
- if (key.getRepositoryId() == repo.asInt())
+ if (key.getRepositoryId() == repo.asInt() && index != null)
return index.findOffset(objId);
return -1;
}
diff --git a/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/Prefetcher.java b/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/Prefetcher.java
index 743f1f5944..fef2b4f29d 100644
--- a/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/Prefetcher.java
+++ b/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/Prefetcher.java
@@ -104,7 +104,7 @@ class Prefetcher implements StreamingCallback<Collection<PackChunk.Members>> {
private DhtException error;
- Prefetcher(DhtReader reader, int objectType) {
+ Prefetcher(DhtReader reader, int objectType, int prefetchLimitInBytes) {
this.db = reader.getDatabase();
this.stats = reader.getStatistics();
this.objectType = objectType;
@@ -113,7 +113,7 @@ class Prefetcher implements StreamingCallback<Collection<PackChunk.Members>> {
this.queue = new LinkedList<ChunkKey>();
this.followEdgeHints = reader.getOptions().isPrefetchFollowEdgeHints();
this.averageChunkSize = reader.getInserterOptions().getChunkSize();
- this.highWaterMark = reader.getOptions().getPrefetchLimit();
+ this.highWaterMark = prefetchLimitInBytes;
int lwm = (highWaterMark / averageChunkSize) - 4;
if (lwm <= 0)
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 f75e3bdc82..22608ee1b3 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;
@@ -55,9 +56,11 @@ final class RecentChunks {
private final DhtReader.Statistics stats;
- private final int maxSize;
+ private final HashMap<ChunkKey, Node> byKey;
- private int curSize;
+ private int maxBytes;
+
+ private int curBytes;
private Node lruHead;
@@ -66,38 +69,56 @@ final class RecentChunks {
RecentChunks(DhtReader reader) {
this.reader = reader;
this.stats = reader.getStatistics();
- this.maxSize = reader.getOptions().getRecentChunkCacheSize();
+ this.byKey = new HashMap<ChunkKey, Node>();
+ this.maxBytes = reader.getOptions().getChunkLimit();
+ }
+
+ void setMaxBytes(int newMax) {
+ maxBytes = Math.max(0, newMax);
+ if (0 < maxBytes)
+ prune();
+ else
+ clear();
}
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;
- }
+ curBytes += chunk.getTotalSize();
+ prune();
+
+ n = new Node();
n.chunk = chunk;
- hit(n);
+ byKey.put(chunk.getChunkKey(), n);
+ first(n);
+ }
+
+ private void prune() {
+ while (maxBytes < curBytes) {
+ Node n = lruTail;
+ if (n == null)
+ break;
+
+ PackChunk c = n.chunk;
+ curBytes -= c.getTotalSize();
+ byKey.remove(c.getChunkKey());
+ remove(n);
+ }
}
ObjectLoader open(RepositoryKey repo, AnyObjectId objId, int typeHint)
@@ -164,9 +185,10 @@ final class RecentChunks {
}
void clear() {
- curSize = 0;
+ curBytes = 0;
lruHead = null;
lruTail = null;
+ byKey.clear();
}
private void hit(Node n) {