summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn Pearce <spearce@spearce.org>2015-05-09 19:53:53 -0700
committerShawn Pearce <spearce@spearce.org>2015-05-11 11:39:28 -0700
commit2eb16aa6ca5415ae4e741c4d1056890e07fa27e5 (patch)
tree5831a5c312470b9f125c9999cb0a0e0546fef2aa
parent8ff08455f62f5696b718ff558507cce3709d604b (diff)
downloadjgit-2eb16aa6ca5415ae4e741c4d1056890e07fa27e5.tar.gz
jgit-2eb16aa6ca5415ae4e741c4d1056890e07fa27e5.zip
Remove SoftReference from dfs.DeltaBaseCache
The Java GC doesn't always clear these before running out of memory and failing allocations. In practice OpenJDK 7 is leaving these live, removing any advantage of the SoftReference to attempt to shed memory when the GC is unable to continue allocating. Instead follow the pattern of the DfsBlockCache and use hard refs to the object data. Require applications to configure the cache size more accurately given expected memory usage. Change-Id: I87586b3e71b1cba0308a6a278d42e971be4bccd3
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DeltaBaseCache.java85
1 files changed, 31 insertions, 54 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DeltaBaseCache.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DeltaBaseCache.java
index c7bdbff8a6..64a63d7c75 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DeltaBaseCache.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DeltaBaseCache.java
@@ -43,7 +43,6 @@
package org.eclipse.jgit.internal.storage.dfs;
-import java.lang.ref.SoftReference;
/**
* Caches recently used objects for {@link DfsReader}.
@@ -60,14 +59,12 @@ final class DeltaBaseCache {
}
private int maxByteCount;
+ private int curByteCount;
- private final Slot[] table;
-
- private Slot lruHead;
+ private final Entry[] table;
- private Slot lruTail;
-
- private int curByteCount;
+ private Entry lruHead;
+ private Entry lruTail;
DeltaBaseCache(DfsReader reader) {
this(reader.getOptions().getDeltaBaseCacheLimit());
@@ -75,19 +72,15 @@ final class DeltaBaseCache {
DeltaBaseCache(int maxBytes) {
maxByteCount = maxBytes;
- table = new Slot[1 << TABLE_BITS];
+ table = new Entry[1 << TABLE_BITS];
}
Entry get(DfsPackKey key, long position) {
- Slot e = table[hash(position)];
+ Entry e = table[hash(position)];
for (; e != null; e = e.tableNext) {
if (e.offset == position && key.equals(e.pack)) {
- Entry buf = e.data.get();
- if (buf != null) {
- moveToHead(e);
- return buf;
- }
- return null;
+ moveToHead(e);
+ return e;
}
}
return null;
@@ -101,8 +94,7 @@ final class DeltaBaseCache {
releaseMemory();
int tableIdx = hash(offset);
- Slot e = new Slot(key, offset, data.length);
- e.data = new SoftReference<Entry>(new Entry(data, objectType));
+ Entry e = new Entry(key, offset, objectType, data);
e.tableNext = table[tableIdx];
table[tableIdx] = e;
lruPushHead(e);
@@ -110,16 +102,16 @@ final class DeltaBaseCache {
private void releaseMemory() {
while (curByteCount > maxByteCount && lruTail != null) {
- Slot e = lruTail;
- curByteCount -= e.size;
+ Entry e = lruTail;
+ curByteCount -= e.data.length;
lruRemove(e);
removeFromTable(e);
}
}
- private void removeFromTable(Slot e) {
+ private void removeFromTable(Entry e) {
int tableIdx = hash(e.offset);
- Slot p = table[tableIdx];
+ Entry p = table[tableIdx];
if (p == e) {
table[tableIdx] = e.tableNext;
@@ -138,16 +130,16 @@ final class DeltaBaseCache {
e.pack, Long.valueOf(e.offset)));
}
- private void moveToHead(final Slot e) {
+ private void moveToHead(Entry e) {
if (e != lruHead) {
lruRemove(e);
lruPushHead(e);
}
}
- private void lruRemove(final Slot e) {
- Slot p = e.lruPrev;
- Slot n = e.lruNext;
+ private void lruRemove(Entry e) {
+ Entry p = e.lruPrev;
+ Entry n = e.lruNext;
if (p != null) {
p.lruNext = n;
@@ -162,8 +154,8 @@ final class DeltaBaseCache {
}
}
- private void lruPushHead(final Slot e) {
- Slot n = lruHead;
+ private void lruPushHead(Entry e) {
+ Entry n = lruHead;
e.lruNext = n;
if (n != null)
n.lruPrev = e;
@@ -180,8 +172,8 @@ final class DeltaBaseCache {
int getMemoryUsedByLruChainForTest() {
int r = 0;
- for (Slot e = lruHead; e != null; e = e.lruNext) {
- r += e.size;
+ for (Entry e = lruHead; e != null; e = e.lruNext) {
+ r += e.data.length;
}
return r;
}
@@ -189,43 +181,28 @@ final class DeltaBaseCache {
int getMemoryUsedByTableForTest() {
int r = 0;
for (int i = 0; i < table.length; i++) {
- for (Slot e = table[i]; e != null; e = e.tableNext) {
- r += e.size;
+ for (Entry e = table[i]; e != null; e = e.tableNext) {
+ r += e.data.length;
}
}
return r;
}
static class Entry {
- final byte[] data;
-
- final int type;
-
- Entry(final byte[] aData, final int aType) {
- data = aData;
- type = aType;
- }
- }
-
- private static class Slot {
final DfsPackKey pack;
-
final long offset;
+ final int type;
+ final byte[] data;
- final int size;
-
- Slot tableNext;
-
- Slot lruPrev;
-
- Slot lruNext;
-
- SoftReference<Entry> data;
+ Entry tableNext;
+ Entry lruPrev;
+ Entry lruNext;
- Slot(DfsPackKey key, long offset, int size) {
+ Entry(DfsPackKey key, long offset, int type, byte[] data) {
this.pack = key;
this.offset = offset;
- this.size = size;
+ this.type = type;
+ this.data = data;
}
}
}