From 5ef0223461a71557658c76ad4092d10ee4f1973e Mon Sep 17 00:00:00 2001 From: "slav.babanin" Date: Fri, 28 Mar 2025 18:26:10 -0700 Subject: [PATCH 1/4] Add String cache for BsonArray indexes. --- bson/src/main/org/bson/BsonBinaryWriter.java | 17 ++++++++-- .../unit/org/bson/BsonBinaryWriterTest.java | 34 ++++++++++++++----- 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/bson/src/main/org/bson/BsonBinaryWriter.java b/bson/src/main/org/bson/BsonBinaryWriter.java index e6255ea8478..f88e551310f 100644 --- a/bson/src/main/org/bson/BsonBinaryWriter.java +++ b/bson/src/main/org/bson/BsonBinaryWriter.java @@ -37,8 +37,16 @@ public class BsonBinaryWriter extends AbstractBsonWriter { private final BsonOutput bsonOutput; private final Stack maxDocumentSizeStack = new Stack<>(); + private static final int ARRAY_INDEXES_CACHE_SIZE = 1 << 8; + private static final String[] ARRAY_INDEXES_CACHE = new String[ARRAY_INDEXES_CACHE_SIZE]; private Mark mark; + static { + for (int i = 0; i < ARRAY_INDEXES_CACHE_SIZE; i++) { + ARRAY_INDEXES_CACHE[i] = Integer.toString(i); + } + } + /** * Construct an instance. * @@ -397,7 +405,12 @@ public void reset() { private void writeCurrentName() { if (getContext().getContextType() == BsonContextType.ARRAY) { - bsonOutput.writeCString(Integer.toString(getContext().index++)); + int index = getContext().index++; + if (index >= ARRAY_INDEXES_CACHE_SIZE) { + bsonOutput.writeCString(Integer.toString(index)); + } else { + bsonOutput.writeCString(ARRAY_INDEXES_CACHE[index]); + } } else { bsonOutput.writeCString(getName()); } @@ -476,4 +489,4 @@ protected void reset() { bsonOutput.truncateToPosition(mark.position); } } -} +} \ No newline at end of file diff --git a/bson/src/test/unit/org/bson/BsonBinaryWriterTest.java b/bson/src/test/unit/org/bson/BsonBinaryWriterTest.java index 8e0f7c23c28..bda2a686e52 100644 --- a/bson/src/test/unit/org/bson/BsonBinaryWriterTest.java +++ b/bson/src/test/unit/org/bson/BsonBinaryWriterTest.java @@ -26,6 +26,7 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; import java.util.List; import static java.util.Arrays.asList; @@ -49,7 +50,7 @@ public class BsonBinaryWriterTest { @BeforeEach public void setup() { buffer = new BasicOutputBuffer(); - writer = new BsonBinaryWriter(new BsonWriterSettings(100), new BsonBinaryWriterSettings(1024), buffer); + writer = new BsonBinaryWriter(new BsonWriterSettings(100), new BsonBinaryWriterSettings(12904), buffer); } @AfterEach @@ -61,7 +62,7 @@ public void tearDown() { public void shouldThrowWhenMaxDocumentSizeIsExceeded() { try { writer.writeStartDocument(); - writer.writeBinaryData("b", new BsonBinary(new byte[1024])); + writer.writeBinaryData("b", new BsonBinary(new byte[12904])); writer.writeEndDocument(); fail(); } catch (BsonMaximumSizeExceededException e) { @@ -197,16 +198,33 @@ public void testWriteArray() { } @Test - public void testWriteArrayElements() { - + public void testWriteArrayElements() throws IOException { + ByteArrayOutputStream expectedOutput = new ByteArrayOutputStream(); writer.writeStartDocument(); writer.writeStartArray("a1"); - writer.writeBoolean(true); - writer.writeBoolean(false); + expectedOutput.write(new byte[]{ + 88, 11, 0, 0, //document length + 4, 97, 49, 0, + 79, 11, 0, 0}); // array length + + int arrayIndex = 0; + while (arrayIndex < 500) { + writer.writeBoolean(true); + expectedOutput.write(BsonType.BOOLEAN.getValue()); + expectedOutput.write(Integer.toString(arrayIndex++).getBytes(StandardCharsets.UTF_8)); + expectedOutput.write(new byte[]{0, 1}); + + writer.writeBoolean(false); + expectedOutput.write(BsonType.BOOLEAN.getValue()); + expectedOutput.write(Integer.toString(arrayIndex++).getBytes(StandardCharsets.UTF_8)); + expectedOutput.write(new byte[]{0, 0}); + } writer.writeEndArray(); + expectedOutput.write(0); writer.writeEndDocument(); - byte[] expectedValues = {22, 0, 0, 0, 4, 97, 49, 0, 13, 0, 0, 0, 8, 48, 0, 1, 8, 49, 0, 0, 0, 0}; - assertArrayEquals(expectedValues, buffer.toByteArray()); + expectedOutput.write(0); + + assertArrayEquals(expectedOutput.toByteArray(), buffer.toByteArray()); } @Test From 5f1eb46623ca8f3620d3b7d4a503d9144e9b83db Mon Sep 17 00:00:00 2001 From: "slav.babanin" Date: Sat, 29 Mar 2025 15:32:57 -0700 Subject: [PATCH 2/4] Add additional comments to a test for clarity. --- .../unit/org/bson/BsonBinaryWriterTest.java | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/bson/src/test/unit/org/bson/BsonBinaryWriterTest.java b/bson/src/test/unit/org/bson/BsonBinaryWriterTest.java index bda2a686e52..84f2aeca65d 100644 --- a/bson/src/test/unit/org/bson/BsonBinaryWriterTest.java +++ b/bson/src/test/unit/org/bson/BsonBinaryWriterTest.java @@ -200,29 +200,35 @@ public void testWriteArray() { @Test public void testWriteArrayElements() throws IOException { ByteArrayOutputStream expectedOutput = new ByteArrayOutputStream(); - writer.writeStartDocument(); - writer.writeStartArray("a1"); expectedOutput.write(new byte[]{ 88, 11, 0, 0, //document length - 4, 97, 49, 0, + 4, // array type + 97, 49, 0, // "a1" name + null terminator 79, 11, 0, 0}); // array length + + writer.writeStartDocument(); + writer.writeStartArray("a1"); int arrayIndex = 0; while (arrayIndex < 500) { writer.writeBoolean(true); + expectedOutput.write(BsonType.BOOLEAN.getValue()); expectedOutput.write(Integer.toString(arrayIndex++).getBytes(StandardCharsets.UTF_8)); - expectedOutput.write(new byte[]{0, 1}); + expectedOutput.write(0); // null terminator + expectedOutput.write(1); // boolean value writer.writeBoolean(false); + expectedOutput.write(BsonType.BOOLEAN.getValue()); expectedOutput.write(Integer.toString(arrayIndex++).getBytes(StandardCharsets.UTF_8)); - expectedOutput.write(new byte[]{0, 0}); + expectedOutput.write(0); // null terminator + expectedOutput.write(0); // boolean value } writer.writeEndArray(); - expectedOutput.write(0); + expectedOutput.write(0); // end of array writer.writeEndDocument(); - expectedOutput.write(0); + expectedOutput.write(0); // end of a document assertArrayEquals(expectedOutput.toByteArray(), buffer.toByteArray()); } From 7e4d5890fbc2a1ad590d77c2cc29550b92f53835 Mon Sep 17 00:00:00 2001 From: "slav.babanin" Date: Mon, 31 Mar 2025 21:25:01 -0700 Subject: [PATCH 3/4] Fix static checks. JAVA-5836 --- bson/src/main/org/bson/BsonBinaryWriter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bson/src/main/org/bson/BsonBinaryWriter.java b/bson/src/main/org/bson/BsonBinaryWriter.java index f88e551310f..c278ccc8d2e 100644 --- a/bson/src/main/org/bson/BsonBinaryWriter.java +++ b/bson/src/main/org/bson/BsonBinaryWriter.java @@ -489,4 +489,4 @@ protected void reset() { bsonOutput.truncateToPosition(mark.position); } } -} \ No newline at end of file +} From fd61c358c7e60bc7ef4e2f81c658b3e6d517c30b Mon Sep 17 00:00:00 2001 From: Viacheslav Babanin Date: Tue, 1 Apr 2025 17:59:35 -0700 Subject: [PATCH 4/4] Update bson/src/main/org/bson/BsonBinaryWriter.java Co-authored-by: Ross Lawley --- bson/src/main/org/bson/BsonBinaryWriter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bson/src/main/org/bson/BsonBinaryWriter.java b/bson/src/main/org/bson/BsonBinaryWriter.java index c278ccc8d2e..dd0a3e1ffaf 100644 --- a/bson/src/main/org/bson/BsonBinaryWriter.java +++ b/bson/src/main/org/bson/BsonBinaryWriter.java @@ -37,7 +37,7 @@ public class BsonBinaryWriter extends AbstractBsonWriter { private final BsonOutput bsonOutput; private final Stack maxDocumentSizeStack = new Stack<>(); - private static final int ARRAY_INDEXES_CACHE_SIZE = 1 << 8; + private static final int ARRAY_INDEXES_CACHE_SIZE = 256; private static final String[] ARRAY_INDEXES_CACHE = new String[ARRAY_INDEXES_CACHE_SIZE]; private Mark mark;