From 4155741f7f486537d4a5f7193d79098d523a6ae8 Mon Sep 17 00:00:00 2001 From: Shay Banon Date: Fri, 6 Sep 2013 02:25:17 +0200 Subject: [PATCH] BytesStreamOutput default size should be 2k instead of 32k We changed the default of BytesStreamOutput (used in various places in ES) to 32k from 1k with the assumption that most stream tend to be large. This doesn't hold for example when indexing small documents and adding them using XContentBuilder (which will have a large overhead). Default the buffer size to 2k now, but be relatively aggressive in expanding the buffer when below 256k (double it), and just use oversize (1/8th) when larger to try and minimize garbage and buffer copies. relates to #3624 closes #3638 --- .../common/io/stream/BytesStreamOutput.java | 22 +++++++++++++++---- .../common/io/streams/BytesStreamsTests.java | 13 +++++++++++ 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/elasticsearch/common/io/stream/BytesStreamOutput.java b/src/main/java/org/elasticsearch/common/io/stream/BytesStreamOutput.java index 378a5fecb7ac8..52756377b5a3e 100644 --- a/src/main/java/org/elasticsearch/common/io/stream/BytesStreamOutput.java +++ b/src/main/java/org/elasticsearch/common/io/stream/BytesStreamOutput.java @@ -31,7 +31,9 @@ */ public class BytesStreamOutput extends StreamOutput implements BytesStream { - public static final int DEFAULT_SIZE = 32 * 1024; + public static final int DEFAULT_SIZE = 2 * 1024; + + public static final int OVERSIZE_LIMIT = 256 * 1024; /** * The buffer where data is stored. @@ -73,7 +75,7 @@ public void seek(long position) throws IOException { public void writeByte(byte b) throws IOException { int newcount = count + 1; if (newcount > buf.length) { - buf = ArrayUtil.grow(buf, newcount); + buf = grow(newcount); } buf[count] = b; count = newcount; @@ -82,7 +84,7 @@ public void writeByte(byte b) throws IOException { public void skip(int length) { int newcount = count + length; if (newcount > buf.length) { - buf = ArrayUtil.grow(buf, newcount); + buf = grow(newcount); } count = newcount; } @@ -94,12 +96,20 @@ public void writeBytes(byte[] b, int offset, int length) throws IOException { } int newcount = count + length; if (newcount > buf.length) { - buf = ArrayUtil.grow(buf, newcount); + buf = grow(newcount); } System.arraycopy(b, offset, buf, count, length); count = newcount; } + private byte[] grow(int newCount) { + // try and grow faster while we are small... + if (newCount < OVERSIZE_LIMIT) { + newCount = Math.max(buf.length << 1, newCount); + } + return ArrayUtil.grow(buf, newCount); + } + public void seek(int seekTo) { count = seekTo; } @@ -108,6 +118,10 @@ public void reset() { count = 0; } + public int bufferSize() { + return buf.length; + } + @Override public void flush() throws IOException { // nothing to do there diff --git a/src/test/java/org/elasticsearch/test/unit/common/io/streams/BytesStreamsTests.java b/src/test/java/org/elasticsearch/test/unit/common/io/streams/BytesStreamsTests.java index c1f4dc450e30c..d4ee4fff5351f 100644 --- a/src/test/java/org/elasticsearch/test/unit/common/io/streams/BytesStreamsTests.java +++ b/src/test/java/org/elasticsearch/test/unit/common/io/streams/BytesStreamsTests.java @@ -60,4 +60,17 @@ public void testSimpleStreams() throws Exception { assertThat(in.readString(), equalTo("hello")); assertThat(in.readString(), equalTo("goodbye")); } + + @Test + public void testGrowLogic() throws Exception { + BytesStreamOutput out = new BytesStreamOutput(); + out.writeBytes(new byte[BytesStreamOutput.DEFAULT_SIZE - 5]); + assertThat(out.bufferSize(), equalTo(2048)); // remains the default + out.writeBytes(new byte[1 * 1024]); + assertThat(out.bufferSize(), equalTo(4608)); + out.writeBytes(new byte[32 * 1024]); + assertThat(out.bufferSize(), equalTo(40320)); + out.writeBytes(new byte[32 * 1024]); + assertThat(out.bufferSize(), equalTo(90720)); + } }