Merge "Make DeltaBaseCache per-ObjectReader"
This commit is contained in:
commit
7b3a6ef530
|
@ -54,35 +54,36 @@ private static int hash(final long position) {
|
||||||
return (((int) position) << 22) >>> 22;
|
return (((int) position) << 22) >>> 22;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int maxByteCount;
|
private static volatile int defaultMaxByteCount;
|
||||||
|
|
||||||
private static final Slot[] cache;
|
private final int maxByteCount;
|
||||||
|
|
||||||
private static Slot lruHead;
|
private final Slot[] cache;
|
||||||
|
|
||||||
private static Slot lruTail;
|
private Slot lruHead;
|
||||||
|
|
||||||
private static int openByteCount;
|
private Slot lruTail;
|
||||||
|
|
||||||
|
private int openByteCount;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
DEAD = new SoftReference<Entry>(null);
|
DEAD = new SoftReference<Entry>(null);
|
||||||
maxByteCount = new WindowCacheConfig().getDeltaBaseCacheLimit();
|
reconfigure(new WindowCacheConfig());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void reconfigure(WindowCacheConfig cfg) {
|
||||||
|
defaultMaxByteCount = cfg.getDeltaBaseCacheLimit();
|
||||||
|
}
|
||||||
|
|
||||||
|
DeltaBaseCache() {
|
||||||
|
maxByteCount = defaultMaxByteCount;
|
||||||
cache = new Slot[CACHE_SZ];
|
cache = new Slot[CACHE_SZ];
|
||||||
for (int i = 0; i < CACHE_SZ; i++)
|
|
||||||
cache[i] = new Slot();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static synchronized void reconfigure(final WindowCacheConfig cfg) {
|
Entry get(final PackFile pack, final long position) {
|
||||||
final int dbLimit = cfg.getDeltaBaseCacheLimit();
|
Slot e = cache[hash(position)];
|
||||||
if (maxByteCount != dbLimit) {
|
if (e == null)
|
||||||
maxByteCount = dbLimit;
|
return null;
|
||||||
releaseMemory();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static synchronized Entry get(final PackFile pack, final long position) {
|
|
||||||
final Slot e = cache[hash(position)];
|
|
||||||
if (e.provider == pack && e.position == position) {
|
if (e.provider == pack && e.position == position) {
|
||||||
final Entry buf = e.data.get();
|
final Entry buf = e.data.get();
|
||||||
if (buf != null) {
|
if (buf != null) {
|
||||||
|
@ -93,13 +94,18 @@ static synchronized Entry get(final PackFile pack, final long position) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
static synchronized void store(final PackFile pack, final long position,
|
void store(final PackFile pack, final long position,
|
||||||
final byte[] data, final int objectType) {
|
final byte[] data, final int objectType) {
|
||||||
if (data.length > maxByteCount)
|
if (data.length > maxByteCount)
|
||||||
return; // Too large to cache.
|
return; // Too large to cache.
|
||||||
|
|
||||||
final Slot e = cache[hash(position)];
|
Slot e = cache[hash(position)];
|
||||||
clearEntry(e);
|
if (e == null) {
|
||||||
|
e = new Slot();
|
||||||
|
cache[hash(position)] = e;
|
||||||
|
} else {
|
||||||
|
clearEntry(e);
|
||||||
|
}
|
||||||
|
|
||||||
openByteCount += data.length;
|
openByteCount += data.length;
|
||||||
releaseMemory();
|
releaseMemory();
|
||||||
|
@ -111,7 +117,7 @@ static synchronized void store(final PackFile pack, final long position,
|
||||||
moveToHead(e);
|
moveToHead(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void releaseMemory() {
|
private void releaseMemory() {
|
||||||
while (openByteCount > maxByteCount && lruTail != null) {
|
while (openByteCount > maxByteCount && lruTail != null) {
|
||||||
final Slot currOldest = lruTail;
|
final Slot currOldest = lruTail;
|
||||||
final Slot nextOldest = currOldest.lruPrev;
|
final Slot nextOldest = currOldest.lruPrev;
|
||||||
|
@ -128,16 +134,7 @@ private static void releaseMemory() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static synchronized void purge(final PackFile file) {
|
private void moveToHead(final Slot e) {
|
||||||
for (final Slot e : cache) {
|
|
||||||
if (e.provider == file) {
|
|
||||||
clearEntry(e);
|
|
||||||
unlink(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void moveToHead(final Slot e) {
|
|
||||||
unlink(e);
|
unlink(e);
|
||||||
e.lruPrev = null;
|
e.lruPrev = null;
|
||||||
e.lruNext = lruHead;
|
e.lruNext = lruHead;
|
||||||
|
@ -148,7 +145,7 @@ private static void moveToHead(final Slot e) {
|
||||||
lruHead = e;
|
lruHead = e;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void unlink(final Slot e) {
|
private void unlink(final Slot e) {
|
||||||
final Slot prev = e.lruPrev;
|
final Slot prev = e.lruPrev;
|
||||||
final Slot next = e.lruNext;
|
final Slot next = e.lruNext;
|
||||||
if (prev != null)
|
if (prev != null)
|
||||||
|
@ -157,17 +154,13 @@ private static void unlink(final Slot e) {
|
||||||
next.lruPrev = prev;
|
next.lruPrev = prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void clearEntry(final Slot e) {
|
private void clearEntry(final Slot e) {
|
||||||
openByteCount -= e.sz;
|
openByteCount -= e.sz;
|
||||||
e.provider = null;
|
e.provider = null;
|
||||||
e.data = DEAD;
|
e.data = DEAD;
|
||||||
e.sz = 0;
|
e.sz = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private DeltaBaseCache() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
static class Entry {
|
static class Entry {
|
||||||
final byte[] data;
|
final byte[] data;
|
||||||
|
|
||||||
|
|
|
@ -236,7 +236,6 @@ void resolve(Set<ObjectId> matches, AbbreviatedObjectId id, int matchLimit)
|
||||||
* Close the resources utilized by this repository
|
* Close the resources utilized by this repository
|
||||||
*/
|
*/
|
||||||
public void close() {
|
public void close() {
|
||||||
DeltaBaseCache.purge(this);
|
|
||||||
WindowCache.purge(this);
|
WindowCache.purge(this);
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
loadedIdx = null;
|
loadedIdx = null;
|
||||||
|
@ -723,7 +722,7 @@ ObjectLoader load(final WindowCursor curs, long pos)
|
||||||
if (sz != delta.deltaSize)
|
if (sz != delta.deltaSize)
|
||||||
break SEARCH;
|
break SEARCH;
|
||||||
|
|
||||||
DeltaBaseCache.Entry e = DeltaBaseCache.get(this, base);
|
DeltaBaseCache.Entry e = curs.getDeltaBaseCache().get(this, base);
|
||||||
if (e != null) {
|
if (e != null) {
|
||||||
type = e.type;
|
type = e.type;
|
||||||
data = e.data;
|
data = e.data;
|
||||||
|
@ -741,7 +740,7 @@ ObjectLoader load(final WindowCursor curs, long pos)
|
||||||
if (sz != delta.deltaSize)
|
if (sz != delta.deltaSize)
|
||||||
break SEARCH;
|
break SEARCH;
|
||||||
|
|
||||||
DeltaBaseCache.Entry e = DeltaBaseCache.get(this, base);
|
DeltaBaseCache.Entry e = curs.getDeltaBaseCache().get(this, base);
|
||||||
if (e != null) {
|
if (e != null) {
|
||||||
type = e.type;
|
type = e.type;
|
||||||
data = e.data;
|
data = e.data;
|
||||||
|
@ -769,7 +768,7 @@ ObjectLoader load(final WindowCursor curs, long pos)
|
||||||
if (cached)
|
if (cached)
|
||||||
cached = false;
|
cached = false;
|
||||||
else if (delta.next == null)
|
else if (delta.next == null)
|
||||||
DeltaBaseCache.store(this, delta.basePos, data, type);
|
curs.getDeltaBaseCache().store(this, delta.basePos, data, type);
|
||||||
|
|
||||||
pos = delta.deltaPos;
|
pos = delta.deltaPos;
|
||||||
|
|
||||||
|
|
|
@ -83,12 +83,20 @@ final class WindowCursor extends ObjectReader implements ObjectReuseAsIs {
|
||||||
|
|
||||||
private ByteWindow window;
|
private ByteWindow window;
|
||||||
|
|
||||||
|
private DeltaBaseCache baseCache;
|
||||||
|
|
||||||
final FileObjectDatabase db;
|
final FileObjectDatabase db;
|
||||||
|
|
||||||
WindowCursor(FileObjectDatabase db) {
|
WindowCursor(FileObjectDatabase db) {
|
||||||
this.db = db;
|
this.db = db;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DeltaBaseCache getDeltaBaseCache() {
|
||||||
|
if (baseCache == null)
|
||||||
|
baseCache = new DeltaBaseCache();
|
||||||
|
return baseCache;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ObjectReader newReader() {
|
public ObjectReader newReader() {
|
||||||
return new WindowCursor(db);
|
return new WindowCursor(db);
|
||||||
|
@ -334,6 +342,7 @@ int getStreamFileThreshold() {
|
||||||
/** Release the current window cursor. */
|
/** Release the current window cursor. */
|
||||||
public void release() {
|
public void release() {
|
||||||
window = null;
|
window = null;
|
||||||
|
baseCache = null;
|
||||||
try {
|
try {
|
||||||
InflaterCache.release(inf);
|
InflaterCache.release(inf);
|
||||||
} finally {
|
} finally {
|
||||||
|
|
Loading…
Reference in New Issue