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$
|
$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
|
1.9 RC1
|
||||||
|
|
||||||
Note that this realease is mostly but not 100% source compatible with the
|
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)
|
* @see IndexInput#readBytes(byte[],int,int)
|
||||||
*/
|
*/
|
||||||
public void writeBytes(byte[] b, int length) throws IOException {
|
public void writeBytes(byte[] b, int length) throws IOException {
|
||||||
for (int i = 0; i < length; i++)
|
int bytesLeft = BUFFER_SIZE - bufferPosition;
|
||||||
writeByte(b[i]);
|
// 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. */
|
/** Forces any buffered output to be written. */
|
||||||
|
|
|
@ -66,27 +66,27 @@ public class RAMOutputStream extends BufferedIndexOutput {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void flushBuffer(byte[] src, int len) {
|
public void flushBuffer(byte[] src, int len) {
|
||||||
int bufferNumber = pointer/BUFFER_SIZE;
|
byte[] buffer;
|
||||||
int bufferOffset = pointer%BUFFER_SIZE;
|
int bufferPos = 0;
|
||||||
int bytesInBuffer = BUFFER_SIZE - bufferOffset;
|
while (bufferPos != len) {
|
||||||
int bytesToCopy = bytesInBuffer >= len ? len : bytesInBuffer;
|
int bufferNumber = pointer/BUFFER_SIZE;
|
||||||
|
int bufferOffset = pointer%BUFFER_SIZE;
|
||||||
|
int bytesInBuffer = BUFFER_SIZE - bufferOffset;
|
||||||
|
int remainInSrcBuffer = len - bufferPos;
|
||||||
|
int bytesToCopy = bytesInBuffer >= remainInSrcBuffer ? remainInSrcBuffer : bytesInBuffer;
|
||||||
|
|
||||||
if (bufferNumber == file.buffers.size())
|
if (bufferNumber == file.buffers.size()) {
|
||||||
file.buffers.addElement(new byte[BUFFER_SIZE]);
|
buffer = new byte[BUFFER_SIZE];
|
||||||
|
file.buffers.addElement(buffer);
|
||||||
|
} else {
|
||||||
|
buffer = (byte[]) file.buffers.elementAt(bufferNumber);
|
||||||
|
}
|
||||||
|
|
||||||
byte[] buffer = (byte[])file.buffers.elementAt(bufferNumber);
|
System.arraycopy(src, bufferPos, buffer, bufferOffset, bytesToCopy);
|
||||||
System.arraycopy(src, 0, buffer, bufferOffset, bytesToCopy);
|
bufferPos += bytesToCopy;
|
||||||
|
pointer += 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);
|
|
||||||
}
|
}
|
||||||
pointer += len;
|
|
||||||
if (pointer > file.length)
|
if (pointer > file.length)
|
||||||
file.length = pointer;
|
file.length = pointer;
|
||||||
|
|
||||||
|
|
|
@ -28,14 +28,13 @@ import java.util.Random;
|
||||||
class StoreTest {
|
class StoreTest {
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
try {
|
try {
|
||||||
test(1000, true);
|
test(1000, true, true);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
System.out.println(" caught a " + e.getClass() +
|
e.printStackTrace();
|
||||||
"\n with message: " + e.getMessage());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void test(int count, boolean ram)
|
public static void test(int count, boolean ram, boolean buffered)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
Random gen = new Random(1251971);
|
Random gen = new Random(1251971);
|
||||||
int i;
|
int i;
|
||||||
|
@ -51,6 +50,8 @@ class StoreTest {
|
||||||
|
|
||||||
final int LENGTH_MASK = 0xFFF;
|
final int LENGTH_MASK = 0xFFF;
|
||||||
|
|
||||||
|
final byte[] buffer = new byte[LENGTH_MASK];
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
String name = i + ".dat";
|
String name = i + ".dat";
|
||||||
int length = gen.nextInt() & LENGTH_MASK;
|
int length = gen.nextInt() & LENGTH_MASK;
|
||||||
|
@ -59,8 +60,14 @@ class StoreTest {
|
||||||
|
|
||||||
IndexOutput file = store.createOutput(name);
|
IndexOutput file = store.createOutput(name);
|
||||||
|
|
||||||
for (int j = 0; j < length; j++)
|
if (buffered) {
|
||||||
file.writeByte(b);
|
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();
|
file.close();
|
||||||
}
|
}
|
||||||
|
@ -89,9 +96,18 @@ class StoreTest {
|
||||||
if (file.length() != length)
|
if (file.length() != length)
|
||||||
throw new Exception("length incorrect");
|
throw new Exception("length incorrect");
|
||||||
|
|
||||||
for (int j = 0; j < length; j++)
|
byte[] content = new byte[length];
|
||||||
if (file.readByte() != b)
|
if (buffered) {
|
||||||
throw new Exception("contents incorrect");
|
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();
|
file.close();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue