From 439d441b08009a82d6d95ee2428c72ffc6ce8b4c Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Wed, 24 Dec 2008 18:11:08 -0800 Subject: [PATCH] Change ByteArrayWindow to read content outside of WindowCache's lock This improves the concurrency limit of WindowCache by allowing the individual windows to be paged in outside of the cache lock. By moving it out multiple threads can read in different windows of the same (or different) pack files concurrently, but we still do only one read per window. Signed-off-by: Shawn O. Pearce Signed-off-by: Robin Rosenberg --- .../src/org/spearce/jgit/lib/ByteArrayWindow.java | 17 +++++++++++++++++ .../src/org/spearce/jgit/lib/WindowCache.java | 2 +- .../src/org/spearce/jgit/lib/WindowedFile.java | 15 +++++++-------- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/ByteArrayWindow.java b/org.spearce.jgit/src/org/spearce/jgit/lib/ByteArrayWindow.java index cea71be1..b32d4f84 100644 --- a/org.spearce.jgit/src/org/spearce/jgit/lib/ByteArrayWindow.java +++ b/org.spearce.jgit/src/org/spearce/jgit/lib/ByteArrayWindow.java @@ -38,6 +38,8 @@ package org.spearce.jgit.lib; +import java.io.IOException; +import java.nio.ByteBuffer; import java.util.zip.DataFormatException; import java.util.zip.Inflater; @@ -45,6 +47,8 @@ import java.util.zip.Inflater; * A {@link ByteWindow} with an underlying byte array for storage. */ final class ByteArrayWindow extends ByteWindow { + boolean loaded; + /** * Constructor for ByteWindow. * @@ -64,6 +68,7 @@ final class ByteArrayWindow extends ByteWindow { } int copy(final byte[] array, final int p, final byte[] b, final int o, int n) { + ensureLoaded(array); n = Math.min(array.length - p, n); System.arraycopy(array, p, b, o, n); return n; @@ -71,6 +76,7 @@ final class ByteArrayWindow extends ByteWindow { int inflate(final byte[] array, final int pos, final byte[] b, int o, final Inflater inf) throws DataFormatException { + ensureLoaded(array); while (!inf.finished()) { if (inf.needsInput()) { inf.setInput(array, pos, array.length - pos); @@ -82,4 +88,15 @@ final class ByteArrayWindow extends ByteWindow { o += inf.inflate(b, o, b.length - o); return o; } + + private synchronized void ensureLoaded(final byte[] array) { + if (!loaded) { + try { + provider.fd.getChannel().read(ByteBuffer.wrap(array), start); + } catch (IOException e) { + throw new RuntimeException("Cannot fault in window", e); + } + loaded = true; + } + } } \ No newline at end of file diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/WindowCache.java b/org.spearce.jgit/src/org/spearce/jgit/lib/WindowCache.java index e71ca73e..0077f529 100644 --- a/org.spearce.jgit/src/org/spearce/jgit/lib/WindowCache.java +++ b/org.spearce.jgit/src/org/spearce/jgit/lib/WindowCache.java @@ -274,7 +274,7 @@ public class WindowCache { releaseMemory(); runClearedWindowQueue(); - wp.loadWindow(curs, id, id << windowSizeShift, wsz); + wp.allocWindow(curs, id, id << windowSizeShift, wsz); final ByteWindow e = curs.window; e.chainNext = cache[idx]; cache[idx] = e; diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/WindowedFile.java b/org.spearce.jgit/src/org/spearce/jgit/lib/WindowedFile.java index 9c5cf1e9..76266934 100644 --- a/org.spearce.jgit/src/org/spearce/jgit/lib/WindowedFile.java +++ b/org.spearce.jgit/src/org/spearce/jgit/lib/WindowedFile.java @@ -73,7 +73,7 @@ public class WindowedFile { final int hash; - private RandomAccessFile fd; + RandomAccessFile fd; private long length; @@ -298,8 +298,8 @@ public class WindowedFile { fd = null; } - void loadWindow(final WindowCursor curs, final int windowId, - final long pos, final int size) throws IOException { + void allocWindow(final WindowCursor curs, final int windowId, + final long pos, final int size) { if (WindowCache.mmap) { MappedByteBuffer map; try { @@ -323,7 +323,10 @@ public class WindowedFile { if (map != null) { if (map.hasArray()) { final byte[] b = map.array(); - curs.window = new ByteArrayWindow(this, pos, windowId, b); + final ByteArrayWindow w; + w = new ByteArrayWindow(this, pos, windowId, b); + w.loaded = true; + curs.window = w; curs.handle = b; } else { curs.window = new ByteBufferWindow(this, pos, windowId, map); @@ -334,10 +337,6 @@ public class WindowedFile { } final byte[] b = new byte[size]; - synchronized (fd) { - fd.seek(pos); - fd.readFully(b); - } curs.window = new ByteArrayWindow(this, pos, windowId, b); curs.handle = b; } -- 2.11.4.GIT