summaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit
diff options
context:
space:
mode:
authorDave Borowitz <dborowitz@google.com>2015-03-18 11:04:26 -0700
committerDave Borowitz <dborowitz@google.com>2015-03-18 13:38:57 -0700
commitedf4368b0c29e25bb74ec0e8f12070582a580eea (patch)
tree31d0bf5fbaf5f4cd3b9cf44f0907c026bf79dd1d /org.eclipse.jgit
parent89b91ad40677c7048d31925986e48150e975bcce (diff)
downloadjgit-edf4368b0c29e25bb74ec0e8f12070582a580eea.tar.gz
jgit-edf4368b0c29e25bb74ec0e8f12070582a580eea.zip
TemporaryBuffer: Allow presizing block pointer list
Callers may wish to use TemporaryBuffer as an essentially unbounded buffer by passing Integer.MAX_VALUE as the size. (This makes it behave like ByteArrayOutputStream, only without requiring contiguous memory.) Unfortunately, it was always allocating an array in the backing block pointer list to hold enough blocks to MAX_VALUE--all 262,016 of them. It wasn't allocating the blocks themselves, but this array was still extremely wasteful, using about 2MiB of memory on a 64-bit system. Tweak the interface to specify an estimated size, and only allocate the block pointer list enough entries to hold that size. It's an ArrayList, so if that estimate was wrong, it'll grow. We assume the cost of finding enough contiguous memory to grow that array is acceptable. While we're in there, fix an off-by-one error: due to integer division we were undercounting the number of blocks needed to store n bytes of data as (n / SZ). Change-Id: I794eca3ac4472bcc605b3641e177922aca92b9c0
Diffstat (limited to 'org.eclipse.jgit')
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/TemporaryBuffer.java47
1 files changed, 42 insertions, 5 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/TemporaryBuffer.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/TemporaryBuffer.java
index 10aade4e11..0a8c5945d9 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/TemporaryBuffer.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/TemporaryBuffer.java
@@ -78,6 +78,9 @@ public abstract class TemporaryBuffer extends OutputStream {
*/
private int inCoreLimit;
+ /** Initial size of block list. */
+ private int initialBlocks;
+
/** If {@link #inCoreLimit} has been reached, remainder goes here. */
private OutputStream overflow;
@@ -86,10 +89,28 @@ public abstract class TemporaryBuffer extends OutputStream {
*
* @param limit
* maximum number of bytes to store in memory before entering the
- * overflow output path.
+ * overflow output path; also used as the estimated size.
*/
protected TemporaryBuffer(final int limit) {
- inCoreLimit = limit;
+ this(limit, limit);
+ }
+
+ /**
+ * Create a new empty temporary buffer.
+ *
+ * @param estimatedSize
+ * estimated size of storage used, to size the initial list of
+ * block pointers.
+ * @param limit
+ * maximum number of bytes to store in memory before entering the
+ * overflow output path.
+ * @since 4.0
+ */
+ protected TemporaryBuffer(final int estimatedSize, final int limit) {
+ if (estimatedSize > limit)
+ throw new IllegalArgumentException();
+ this.inCoreLimit = limit;
+ this.initialBlocks = (estimatedSize - 1) / Block.SZ + 1;
reset();
}
@@ -274,7 +295,7 @@ public abstract class TemporaryBuffer extends OutputStream {
blocks = new ArrayList<Block>(1);
blocks.add(new Block(inCoreLimit));
} else {
- blocks = new ArrayList<Block>(inCoreLimit / Block.SZ);
+ blocks = new ArrayList<Block>(initialBlocks);
blocks.add(new Block());
}
}
@@ -498,12 +519,28 @@ public abstract class TemporaryBuffer extends OutputStream {
* Create a new heap buffer with a maximum storage limit.
*
* @param limit
+ * maximum number of bytes that can be stored in this buffer;
+ * also used as the estimated size. Storing beyond this many
+ * will cause an IOException to be thrown during write.
+ */
+ public Heap(final int limit) {
+ super(limit);
+ }
+
+ /**
+ * Create a new heap buffer with a maximum storage limit.
+ *
+ * @param estimatedSize
+ * estimated size of storage used, to size the initial list of
+ * block pointers.
+ * @param limit
* maximum number of bytes that can be stored in this buffer.
* Storing beyond this many will cause an IOException to be
* thrown during write.
+ * @since 4.0
*/
- public Heap(final int limit) {
- super(limit);
+ public Heap(final int estimatedSize, final int limit) {
+ super(estimatedSize, limit);
}
@Override