You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by kr...@apache.org on 2008/08/01 17:24:35 UTC
svn commit: r681723 -
/db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/UTF8Reader.java
Author: kristwaa
Date: Fri Aug 1 08:24:34 2008
New Revision: 681723
URL: http://svn.apache.org/viewvc?rev=681723&view=rev
Log:
DERBY-3791: Excessive memory usage when fetching small Clobs.
Exploits length information (where available) to reduce memory overhead wrt buffering. This improvement will only affect small Clobs in the range 1 byte to 8 KB, the smaller the Clob the bigger the overhead reduction.
Patch file: derby-3791-2a-buffer-adjustments.diff
Modified:
db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/UTF8Reader.java
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/UTF8Reader.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/UTF8Reader.java?rev=681723&r1=681722&r2=681723&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/UTF8Reader.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/UTF8Reader.java Fri Aug 1 08:24:34 2008
@@ -55,6 +55,8 @@
public final class UTF8Reader extends Reader
{
private static final String READER_CLOSED = "Reader closed";
+ /** Maximum size in number of chars for the internal character buffer. */
+ private static final int MAXIMUM_BUFFER_SIZE = 8*1024; // 8 KB
/** The underlying data stream. */
private InputStream in;
@@ -82,7 +84,7 @@
private final long maxFieldSize; // characters
/** Internal character buffer storing characters read from the stream. */
- private final char[] buffer = new char[8 * 1024];
+ private final char[] buffer;
/** The number of characters in the internal buffer. */
private int charactersInBuffer; // within buffer
/** The position of the next character to read in the internal buffer. */
@@ -131,6 +133,7 @@
parent.setupContextStack();
try {
synchronized (lock) { // Synchronize access to store.
+ this.in = in; // Note the possible reassignment below.
if (in instanceof PositionedStoreStream) {
this.positionedIn = (PositionedStoreStream)in;
// This stream is already buffered, and buffering it again
@@ -138,7 +141,6 @@
// implement a special buffered reader to buffer again.
// Note that buffering this UTF8Reader again, does not
// cause any trouble...
- this.in = in;
try {
this.positionedIn.resetStream();
} catch (StandardException se) {
@@ -146,8 +148,6 @@
}
} else {
this.positionedIn = null;
- // Buffer this for improved performance.
- this.in = new BufferedInputStream (in);
}
this.utfLen = readUnsignedShort();
// Even if we are reading the encoded length, the stream may
@@ -160,6 +160,16 @@
} finally {
parent.restoreContextStack();
}
+ // Setup buffering.
+ int bufferSize = calculateBufferSize(utfLen, maxFieldSize);
+ this.buffer = new char[bufferSize];
+ if (this.positionedIn == null) {
+ // Buffer this for improved performance.
+ // Note that the stream buffers bytes, whereas the internal buffer
+ // buffers characters. In worst case, the stream buffer must be
+ // filled three times to fill the internal character buffer.
+ this.in = new BufferedInputStream(in, bufferSize);
+ }
}
/**
@@ -192,8 +202,13 @@
// the stream and we can't pass that out as data to the user.
SanityManager.ASSERT(!(in instanceof Resetable));
}
+ int bufferSize = calculateBufferSize(streamSize, maxFieldSize);
+ this.buffer = new char[bufferSize];
// Buffer this for improved performance.
- this.in = new BufferedInputStream(in);
+ // Note that the stream buffers bytes, whereas the internal buffer
+ // buffers characters. In worst case, the stream buffer must be filled
+ // three times to fill the internal character buffer.
+ this.in = new BufferedInputStream(in, bufferSize);
}
/*
@@ -587,4 +602,25 @@
return (ch1 << 8) + (ch2 << 0);
}
+
+ /**
+ * Calculates an optimized buffer size.
+ * <p>
+ * The maximum size allowed is returned if the specified values don't give
+ * enough information to say a smaller buffer size is preferable.
+ *
+ * @param encodedSize data length in bytes
+ * @param maxFieldSize maximum data length in bytes
+ * @return An (sub)optimal buffer size.
+ */
+ private final int calculateBufferSize(long encodedSize, long maxFieldSize) {
+ int bufferSize = MAXIMUM_BUFFER_SIZE;
+ if (encodedSize > 0 && encodedSize < bufferSize) {
+ bufferSize = (int)encodedSize;
+ }
+ if (maxFieldSize > 0 && maxFieldSize < bufferSize) {
+ bufferSize = (int)maxFieldSize;
+ }
+ return bufferSize;
+ }
}