Skip to content

Commit c15e14a

Browse files
authored
Optimize BsonArray Index encoding (#1673)
JAVA-5836
1 parent 4000d44 commit c15e14a

File tree

2 files changed

+32
-8
lines changed

2 files changed

+32
-8
lines changed

bson/src/main/org/bson/BsonBinaryWriter.java

+28-4
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import java.util.List;
2525
import java.util.Stack;
2626

27+
import static java.lang.Math.max;
2728
import static java.lang.String.format;
2829
import static org.bson.assertions.Assertions.notNull;
2930

@@ -37,13 +38,34 @@ public class BsonBinaryWriter extends AbstractBsonWriter {
3738

3839
private final BsonOutput bsonOutput;
3940
private final Stack<Integer> maxDocumentSizeStack = new Stack<>();
40-
private static final int ARRAY_INDEXES_CACHE_SIZE = 256;
41-
private static final String[] ARRAY_INDEXES_CACHE = new String[ARRAY_INDEXES_CACHE_SIZE];
41+
private static final int ARRAY_INDEXES_CACHE_SIZE = 1000;
42+
private static final byte[] ARRAY_INDEXES_BUFFER;
43+
private static final int[] ARRAY_INDEXES_OFFSETS;
44+
private static final int[] ARRAY_INDEXES_LENGTHS;
4245
private Mark mark;
4346

4447
static {
48+
ARRAY_INDEXES_LENGTHS = new int[ARRAY_INDEXES_CACHE_SIZE];
49+
ARRAY_INDEXES_OFFSETS = new int[ARRAY_INDEXES_CACHE_SIZE];
50+
int totalSize = 0;
4551
for (int i = 0; i < ARRAY_INDEXES_CACHE_SIZE; i++) {
46-
ARRAY_INDEXES_CACHE[i] = Integer.toString(i);
52+
totalSize += (int) (Math.log10(max(i, 1))
53+
+ 1 // number of digits
54+
+ 1); // +1 for null terminator
55+
}
56+
ARRAY_INDEXES_BUFFER = new byte[totalSize];
57+
58+
// Fill buffer
59+
int offset = 0;
60+
for (int i = 0; i < ARRAY_INDEXES_CACHE_SIZE; i++) {
61+
String string = Integer.toString(i);
62+
int length = string.length();
63+
for (int j = 0; j < length; j++) {
64+
ARRAY_INDEXES_BUFFER[offset++] = (byte) string.charAt(j);
65+
}
66+
ARRAY_INDEXES_BUFFER[offset++] = 0;
67+
ARRAY_INDEXES_OFFSETS[i] = offset - (length + 1);
68+
ARRAY_INDEXES_LENGTHS[i] = length + 1; // +1 for null terminator
4769
}
4870
}
4971

@@ -409,7 +431,9 @@ private void writeCurrentName() {
409431
if (index >= ARRAY_INDEXES_CACHE_SIZE) {
410432
bsonOutput.writeCString(Integer.toString(index));
411433
} else {
412-
bsonOutput.writeCString(ARRAY_INDEXES_CACHE[index]);
434+
bsonOutput.writeBytes(ARRAY_INDEXES_BUFFER,
435+
ARRAY_INDEXES_OFFSETS[index],
436+
ARRAY_INDEXES_LENGTHS[index]);
413437
}
414438
} else {
415439
bsonOutput.writeCString(getName());

bson/src/test/unit/org/bson/BsonBinaryWriterTest.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public void shouldThrowWhenMaxDocumentSizeIsExceeded() {
6666
writer.writeEndDocument();
6767
fail();
6868
} catch (BsonMaximumSizeExceededException e) {
69-
assertEquals("Document size of 1037 is larger than maximum of 1024.", e.getMessage());
69+
assertEquals("Document size of 12917 is larger than maximum of 12904.", e.getMessage());
7070
}
7171
}
7272

@@ -201,16 +201,16 @@ public void testWriteArray() {
201201
public void testWriteArrayElements() throws IOException {
202202
ByteArrayOutputStream expectedOutput = new ByteArrayOutputStream();
203203
expectedOutput.write(new byte[]{
204-
88, 11, 0, 0, //document length
204+
-52, 25, 0, 0, //document length
205205
4, // array type
206206
97, 49, 0, // "a1" name + null terminator
207-
79, 11, 0, 0}); // array length
207+
-61, 25, 0, 0}); // array length
208208

209209

210210
writer.writeStartDocument();
211211
writer.writeStartArray("a1");
212212
int arrayIndex = 0;
213-
while (arrayIndex < 500) {
213+
while (arrayIndex < 1100) {
214214
writer.writeBoolean(true);
215215

216216
expectedOutput.write(BsonType.BOOLEAN.getValue());

0 commit comments

Comments
 (0)