Skip to content

Commit 8a179ff

Browse files
Speedup RecyclerBytesStreamOutput.writeString (#113241)
This method is quite hot in some use-cases because it's used by most string writing to transport messages. Overriding teh default implementation for cases where we can write straight to the page instead of going through an intermediary buffer speeds up the method by more than 2x, saving lots of cycles, especially on transport threads.
1 parent 8a94037 commit 8a179ff

File tree

1 file changed

+32
-0
lines changed

1 file changed

+32
-0
lines changed

server/src/main/java/org/elasticsearch/common/io/stream/RecyclerBytesStreamOutput.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,38 @@ public void writeWithSizePrefix(Writeable writeable) throws IOException {
177177
}
178178
}
179179

180+
// overridden with some code duplication the same way other write methods in this class are overridden to bypass StreamOutput's
181+
// intermediary buffers
182+
@Override
183+
public void writeString(String str) throws IOException {
184+
final int currentPageOffset = this.currentPageOffset;
185+
final int charCount = str.length();
186+
// maximum serialized length is 3 bytes per char + 5 bytes for the longest possible vint
187+
if (charCount * 3 + 5 > (pageSize - currentPageOffset)) {
188+
super.writeString(str);
189+
return;
190+
}
191+
BytesRef currentPage = pages.get(pageIndex).v();
192+
int off = currentPage.offset + currentPageOffset;
193+
byte[] buffer = currentPage.bytes;
194+
// mostly duplicated from StreamOutput.writeString to to get more reliable compilation of this very hot loop
195+
int offset = off + putVInt(buffer, charCount, off);
196+
for (int i = 0; i < charCount; i++) {
197+
final int c = str.charAt(i);
198+
if (c <= 0x007F) {
199+
buffer[offset++] = ((byte) c);
200+
} else if (c > 0x07FF) {
201+
buffer[offset++] = ((byte) (0xE0 | c >> 12 & 0x0F));
202+
buffer[offset++] = ((byte) (0x80 | c >> 6 & 0x3F));
203+
buffer[offset++] = ((byte) (0x80 | c >> 0 & 0x3F));
204+
} else {
205+
buffer[offset++] = ((byte) (0xC0 | c >> 6 & 0x1F));
206+
buffer[offset++] = ((byte) (0x80 | c >> 0 & 0x3F));
207+
}
208+
}
209+
this.currentPageOffset = offset - currentPage.offset;
210+
}
211+
180212
@Override
181213
public void flush() {
182214
// nothing to do

0 commit comments

Comments
 (0)