Fix for LUCENE-435: Optimize BufferedIndexOutput.writeBytes(). Contributed by Lukas Zapletal.

git-svn-id: https://svn.apache.org/repos/asf/lucene/java/trunk@379532 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Doug Cutting 2006-02-21 17:00:40 +00:00
parent 2b686b68aa
commit 7c09d17565
4 changed files with 87 additions and 29 deletions

View File

@ -2,6 +2,15 @@ Lucene Change Log
$Id$
1.9 RC2
Optimizations
1. Optimized BufferedIndexOutput.writeBytes() to use
System.arraycopy() in more cases, rather than copying byte-by-byte.
(Lukas Zapletal via Cutting)
1.9 RC1
Note that this realease is mostly but not 100% source compatible with the

View File

@ -41,8 +41,41 @@ public abstract class BufferedIndexOutput extends IndexOutput {
* @see IndexInput#readBytes(byte[],int,int)
*/
public void writeBytes(byte[] b, int length) throws IOException {
for (int i = 0; i < length; i++)
writeByte(b[i]);
int bytesLeft = BUFFER_SIZE - bufferPosition;
// is there enough space in the buffer?
if (bytesLeft >= length) {
// we add the data to the end of the buffer
System.arraycopy(b, 0, buffer, bufferPosition, length);
bufferPosition += length;
// if the buffer is full, flush it
if (BUFFER_SIZE - bufferPosition == 0)
flush();
} else {
// is data larger then buffer?
if (length > BUFFER_SIZE) {
// we flush the buffer
if (bufferPosition > 0)
flush();
// and write data at once
flushBuffer(b, length);
} else {
// we fill/flush the buffer (until the input is written)
int pos = 0; // position in the input data
int pieceLength;
while (pos < length) {
pieceLength = (length - pos < bytesLeft) ? length - pos : bytesLeft;
System.arraycopy(b, pos, buffer, bufferPosition, pieceLength);
pos += pieceLength;
bufferPosition += pieceLength;
// if the buffer is full, flush it
bytesLeft = BUFFER_SIZE - bufferPosition;
if (bytesLeft == 0) {
flush();
bytesLeft = BUFFER_SIZE;
}
}
}
}
}
/** Forces any buffered output to be written. */

View File

@ -66,27 +66,27 @@ public class RAMOutputStream extends BufferedIndexOutput {
}
public void flushBuffer(byte[] src, int len) {
byte[] buffer;
int bufferPos = 0;
while (bufferPos != len) {
int bufferNumber = pointer/BUFFER_SIZE;
int bufferOffset = pointer%BUFFER_SIZE;
int bytesInBuffer = BUFFER_SIZE - bufferOffset;
int bytesToCopy = bytesInBuffer >= len ? len : bytesInBuffer;
int remainInSrcBuffer = len - bufferPos;
int bytesToCopy = bytesInBuffer >= remainInSrcBuffer ? remainInSrcBuffer : bytesInBuffer;
if (bufferNumber == file.buffers.size())
file.buffers.addElement(new byte[BUFFER_SIZE]);
byte[] buffer = (byte[])file.buffers.elementAt(bufferNumber);
System.arraycopy(src, 0, buffer, bufferOffset, bytesToCopy);
if (bytesToCopy < len) { // not all in one buffer
int srcOffset = bytesToCopy;
bytesToCopy = len - bytesToCopy; // remaining bytes
bufferNumber++;
if (bufferNumber == file.buffers.size())
file.buffers.addElement(new byte[BUFFER_SIZE]);
buffer = (byte[])file.buffers.elementAt(bufferNumber);
System.arraycopy(src, srcOffset, buffer, 0, bytesToCopy);
if (bufferNumber == file.buffers.size()) {
buffer = new byte[BUFFER_SIZE];
file.buffers.addElement(buffer);
} else {
buffer = (byte[]) file.buffers.elementAt(bufferNumber);
}
pointer += len;
System.arraycopy(src, bufferPos, buffer, bufferOffset, bytesToCopy);
bufferPos += bytesToCopy;
pointer += bytesToCopy;
}
if (pointer > file.length)
file.length = pointer;

View File

@ -28,14 +28,13 @@ import java.util.Random;
class StoreTest {
public static void main(String[] args) {
try {
test(1000, true);
test(1000, true, true);
} catch (Exception e) {
System.out.println(" caught a " + e.getClass() +
"\n with message: " + e.getMessage());
e.printStackTrace();
}
}
public static void test(int count, boolean ram)
public static void test(int count, boolean ram, boolean buffered)
throws Exception {
Random gen = new Random(1251971);
int i;
@ -51,6 +50,8 @@ class StoreTest {
final int LENGTH_MASK = 0xFFF;
final byte[] buffer = new byte[LENGTH_MASK];
for (i = 0; i < count; i++) {
String name = i + ".dat";
int length = gen.nextInt() & LENGTH_MASK;
@ -59,8 +60,14 @@ class StoreTest {
IndexOutput file = store.createOutput(name);
if (buffered) {
for (int j = 0; j < length; j++)
buffer[j] = b;
file.writeBytes(buffer, length);
} else {
for (int j = 0; j < length; j++)
file.writeByte(b);
}
file.close();
}
@ -89,9 +96,18 @@ class StoreTest {
if (file.length() != length)
throw new Exception("length incorrect");
byte[] content = new byte[length];
if (buffered) {
file.readBytes(content, 0, length);
// check the buffer
for (int j = 0; j < length; j++)
if (content[j] != b)
throw new Exception("contents incorrect");
} else {
for (int j = 0; j < length; j++)
if (file.readByte() != b)
throw new Exception("contents incorrect");
}
file.close();
}