40
40
41
41
import java .io .IOException ;
42
42
import java .io .InputStream ;
43
+ import java .util .HashMap ;
44
+ import java .util .Map ;
43
45
import java .util .function .Consumer ;
46
+ import java .util .function .Function ;
44
47
45
48
import static org .elasticsearch .index .seqno .SequenceNumbers .UNASSIGNED_PRIMARY_TERM ;
46
49
@@ -139,6 +142,10 @@ public void parse(
139
142
int from = 0 ;
140
143
byte marker = xContent .streamSeparator ();
141
144
boolean typesDeprecationLogged = false ;
145
+ // Bulk requests can contain a lot of repeated strings for the index, pipeline and routing parameters. This map is used to
146
+ // deduplicate duplicate strings parsed for these parameters. While it does not prevent instantiating the duplicate strings, it
147
+ // reduces their lifetime to the lifetime of this parse call instead of the lifetime of the full bulk request.
148
+ final Map <String , String > stringDeduplicator = new HashMap <>();
142
149
while (true ) {
143
150
int nextMarker = findNextMarker (marker , from , data );
144
151
if (nextMarker == -1 ) {
@@ -198,17 +205,17 @@ public void parse(
198
205
if (!allowExplicitIndex ) {
199
206
throw new IllegalArgumentException ("explicit index in bulk is not allowed" );
200
207
}
201
- index = parser .text ();
208
+ index = stringDeduplicator . computeIfAbsent ( parser .text (), Function . identity () );
202
209
} else if (TYPE .match (currentFieldName , parser .getDeprecationHandler ())) {
203
210
if (warnOnTypeUsage && typesDeprecationLogged == false ) {
204
211
deprecationLogger .deprecatedAndMaybeLog ("bulk_with_types" , RestBulkAction .TYPES_DEPRECATION_MESSAGE );
205
212
typesDeprecationLogged = true ;
206
213
}
207
- type = parser .text ();
214
+ type = stringDeduplicator . computeIfAbsent ( parser .text (), Function . identity () );
208
215
} else if (ID .match (currentFieldName , parser .getDeprecationHandler ())) {
209
216
id = parser .text ();
210
217
} else if (ROUTING .match (currentFieldName , parser .getDeprecationHandler ())) {
211
- routing = parser .text ();
218
+ routing = stringDeduplicator . computeIfAbsent ( parser .text (), Function . identity () );
212
219
} else if (OP_TYPE .match (currentFieldName , parser .getDeprecationHandler ())) {
213
220
opType = parser .text ();
214
221
} else if (VERSION .match (currentFieldName , parser .getDeprecationHandler ())) {
@@ -222,7 +229,7 @@ public void parse(
222
229
} else if (RETRY_ON_CONFLICT .match (currentFieldName , parser .getDeprecationHandler ())) {
223
230
retryOnConflict = parser .intValue ();
224
231
} else if (PIPELINE .match (currentFieldName , parser .getDeprecationHandler ())) {
225
- pipeline = parser .text ();
232
+ pipeline = stringDeduplicator . computeIfAbsent ( parser .text (), Function . identity () );
226
233
} else if (SOURCE .match (currentFieldName , parser .getDeprecationHandler ())) {
227
234
fetchSourceContext = FetchSourceContext .fromXContent (parser );
228
235
} else {
0 commit comments