mirror of https://github.com/apache/lucene.git
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:
parent
2b686b68aa
commit
7c09d17565
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue