@@ -35,7 +35,11 @@ public class ByteBufferBsonInput implements BsonInput {
35
35
36
36
private static final String [] ONE_BYTE_ASCII_STRINGS = new String [Byte .MAX_VALUE + 1 ];
37
37
private static final boolean UNALIGNED_ACCESS_SUPPORTED = isUnalignedAccessAllowed ();
38
- private int scratchBufferSize = 0 ;
38
+ /* A dynamically sized scratch buffer, that is reused across BSON String reads:
39
+ * 1. Reduces garbage collection by avoiding new byte array creation.
40
+ * 2. Improves cache utilization through temporal locality.
41
+ * 3. Avoids JVM allocation and zeroing cost for new memory allocations.
42
+ */
39
43
private byte [] scratchBuffer ;
40
44
41
45
@@ -136,8 +140,8 @@ public String readCString() {
136
140
return readString (size );
137
141
}
138
142
139
- private String readString (final int stringSize ) {
140
- if (stringSize == 2 ) {
143
+ private String readString (final int bsonStringSize ) {
144
+ if (bsonStringSize == 2 ) {
141
145
byte asciiByte = buffer .get (); // if only one byte in the string, it must be ascii.
142
146
byte nullByte = buffer .get (); // read null terminator
143
147
if (nullByte != 0 ) {
@@ -151,24 +155,24 @@ private String readString(final int stringSize) {
151
155
if (buffer .isBackedByArray ()) {
152
156
int position = buffer .position ();
153
157
int arrayOffset = buffer .arrayOffset ();
154
- int newPosition = position + stringSize ;
158
+ int newPosition = position + bsonStringSize ;
155
159
buffer .position (newPosition );
156
160
157
161
byte [] array = buffer .array ();
158
162
if (array [arrayOffset + newPosition - 1 ] != 0 ) {
159
163
throw new BsonSerializationException ("Found a BSON string that is not null-terminated" );
160
164
}
161
- return new String (array , arrayOffset + position , stringSize - 1 , StandardCharsets .UTF_8 );
162
- } else if (stringSize > scratchBufferSize ) {
163
- scratchBufferSize = stringSize + (stringSize >> 1 ); //1.5 times the size
165
+ return new String (array , arrayOffset + position , bsonStringSize - 1 , StandardCharsets .UTF_8 );
166
+ } else if (scratchBuffer == null || bsonStringSize > scratchBuffer . length ) {
167
+ int scratchBufferSize = bsonStringSize + (bsonStringSize > >> 1 ); //1.5 times the size
164
168
scratchBuffer = new byte [scratchBufferSize ];
165
169
}
166
170
167
- buffer .get (scratchBuffer , 0 , stringSize );
168
- if (scratchBuffer [stringSize - 1 ] != 0 ) {
171
+ buffer .get (scratchBuffer , 0 , bsonStringSize );
172
+ if (scratchBuffer [bsonStringSize - 1 ] != 0 ) {
169
173
throw new BsonSerializationException ("BSON string not null-terminated" );
170
174
}
171
- return new String (scratchBuffer , 0 , stringSize - 1 , StandardCharsets .UTF_8 );
175
+ return new String (scratchBuffer , 0 , bsonStringSize - 1 , StandardCharsets .UTF_8 );
172
176
}
173
177
}
174
178
@@ -180,6 +184,10 @@ public void skipCString() {
180
184
buffer .position (pos + length );
181
185
}
182
186
187
+ /*
188
+ This method uses the SWAR (SIMD Within A Register) technique when aligned access is supported.
189
+ SWAR finds a null terminator by processing 8 bytes at once.
190
+ */
183
191
public int computeCStringLength (final int prevPos ) {
184
192
ensureOpen ();
185
193
int pos = buffer .position ();
0 commit comments