> I don't in general disagree with this sort of optimization, but I think > a good fix is a bit more complicated than what you posted.
Hi Doug, I had some time to redo my fixes... > This forces a flush() each time a byte array of any size is written. > That could be much slower when lots of small byte arrays are written, > since flush() invokes a system call. What would be best is, if there is Yes, I made a better version in an exact way you have described above. The patch replaces writeBytes method with the whole new implementation: public void writeBytes(byte[] b, int length) throws IOException { 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 { // 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; } } } } This is much smarter and it is not slow for lots of one-byte writes. I agree with the assession of my "fix" of readBytes: > Again, this could be much slower when lots of small arrays are written, > since each call forces seek and read system calls. However this could > be optimized for the case where the desired data resides entirely in the > current buffer to use System.arraycopy. So I tried to optimize the reads from buffer, but the method was so complicated I dropped this thought. Readbytes is fast enough. I have modified the StoreTest, now you can test the *byte or *bytes methods (3rd parameter). Because of creating and testing the buffers, there is not speed improvement here but when you write from some prepared buffer (e.g. from a file), the speed increases. -- S pozdravem / Best regards Lukas Zapletal sefredaktor / editor-in-chief LinuxEXPRES - opravdovy linuxovy magazin www.LinuxEXPRES.cz tel.:+420 777 003 843
Index: src/test/org/apache/lucene/StoreTest.java =================================================================== --- src/test/org/apache/lucene/StoreTest.java (revision 290385) +++ src/test/org/apache/lucene/StoreTest.java (working copy) @@ -28,14 +28,13 @@ 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 @@ 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 @@ IndexOutput file = store.createOutput(name); - for (int j = 0; j < length; j++) - file.writeByte(b); + 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 @@ if (file.length() != length) throw new Exception("length incorrect"); - for (int j = 0; j < length; j++) - if (file.readByte() != b) - throw new Exception("contents 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(); } Index: src/java/org/apache/lucene/store/BufferedIndexOutput.java =================================================================== --- src/java/org/apache/lucene/store/BufferedIndexOutput.java (revision 290385) +++ src/java/org/apache/lucene/store/BufferedIndexOutput.java (working copy) @@ -41,8 +41,32 @@ * @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 { + // 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. */
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]