Skip to content

Commit 3f829e4

Browse files
Fix some inefficiencies in FieldsVisitor (#127688)
Just a couple obvious finds. No need to start from `null` here, just makes locality worse to so and adds conditionals. Also, we can save some field lookups and a needless hot allocation of `BytesRef` that isn't guaranteed to be escape analyzed away.
1 parent 483a9ae commit 3f829e4

File tree

1 file changed

+27
-36
lines changed

1 file changed

+27
-36
lines changed

server/src/main/java/org/elasticsearch/index/fieldvisitor/FieldsVisitor.java

+27-36
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@
2929
import java.util.Set;
3030
import java.util.function.Function;
3131

32-
import static java.util.Collections.emptyMap;
33-
3432
/**
3533
* Base {@link StoredFieldVisitor} that retrieves all non-redundant metadata.
3634
*/
@@ -40,9 +38,9 @@ public class FieldsVisitor extends FieldNamesProvidingStoredFieldsVisitor {
4038
private final boolean loadSource;
4139
final String sourceFieldName;
4240
private final Set<String> requiredFields;
43-
protected BytesReference source;
44-
protected String id;
45-
protected Map<String, List<Object>> fieldsValues;
41+
private BytesReference source;
42+
private String id;
43+
private final Map<String, List<Object>> fieldsValues = new HashMap<>();
4644

4745
public FieldsVisitor(boolean loadSource) {
4846
this(loadSource, SourceFieldMapper.NAME);
@@ -58,24 +56,29 @@ public FieldsVisitor(boolean loadSource, String sourceFieldName) {
5856

5957
@Override
6058
public Status needsField(FieldInfo fieldInfo) {
61-
if (requiredFields.remove(fieldInfo.name)) {
59+
final String name = fieldInfo.name;
60+
var requiredFields = this.requiredFields;
61+
if (requiredFields.remove(name)) {
6262
return Status.YES;
6363
}
6464
// Always load _ignored to be explicit about ignored fields
6565
// This works because _ignored is added as the first metadata mapper,
6666
// so its stored fields always appear first in the list.
6767
// Note that _ignored is also multi-valued, which is why it can't be removed from the set like other fields
68-
if (IgnoredFieldMapper.NAME.equals(fieldInfo.name)) {
68+
if (IgnoredFieldMapper.NAME.equals(name)) {
6969
return Status.YES;
7070
}
71+
// All these fields are single-valued so we can stop when the set is empty
72+
if (requiredFields.isEmpty()) {
73+
return Status.STOP;
74+
}
7175
// support _uid for loading older indices
72-
if ("_uid".equals(fieldInfo.name)) {
76+
if ("_uid".equals(name)) {
7377
if (requiredFields.remove(IdFieldMapper.NAME) || requiredFields.remove(LegacyTypeFieldMapper.NAME)) {
7478
return Status.YES;
7579
}
7680
}
77-
// All these fields are single-valued so we can stop when the set is empty
78-
return requiredFields.isEmpty() ? Status.STOP : Status.NO;
81+
return Status.NO;
7982
}
8083

8184
@Override
@@ -98,33 +101,31 @@ public final void postProcess(Function<String, MappedFieldType> fieldTypeLookup)
98101

99102
@Override
100103
public void binaryField(FieldInfo fieldInfo, byte[] value) {
101-
binaryField(fieldInfo, new BytesRef(value));
102-
}
103-
104-
private void binaryField(FieldInfo fieldInfo, BytesRef value) {
105-
if (sourceFieldName.equals(fieldInfo.name)) {
104+
final String name = fieldInfo.name;
105+
if (sourceFieldName.equals(name)) {
106106
source = new BytesArray(value);
107-
} else if (IdFieldMapper.NAME.equals(fieldInfo.name)) {
108-
id = Uid.decodeId(value.bytes, value.offset, value.length);
107+
} else if (IdFieldMapper.NAME.equals(name)) {
108+
id = Uid.decodeId(value, 0, value.length);
109109
} else {
110-
addValue(fieldInfo.name, value);
110+
addValue(name, new BytesRef(value));
111111
}
112112
}
113113

114114
@Override
115115
public void stringField(FieldInfo fieldInfo, String value) {
116-
assert sourceFieldName.equals(fieldInfo.name) == false : "source field must go through binaryField";
117-
if ("_uid".equals(fieldInfo.name)) {
116+
final String name = fieldInfo.name;
117+
assert sourceFieldName.equals(name) == false : "source field must go through binaryField";
118+
if ("_uid".equals(name)) {
118119
// 5.x-only
119120
int delimiterIndex = value.indexOf('#'); // type is not allowed to have # in it..., ids can
120121
String type = value.substring(0, delimiterIndex);
121122
id = value.substring(delimiterIndex + 1);
122123
addValue(LegacyTypeFieldMapper.NAME, type);
123-
} else if (IdFieldMapper.NAME.equals(fieldInfo.name)) {
124+
} else if (IdFieldMapper.NAME.equals(name)) {
124125
// only applies to 5.x indices that have single_type = true
125126
id = value;
126127
} else {
127-
addValue(fieldInfo.name, value);
128+
addValue(name, value);
128129
}
129130
}
130131

@@ -157,25 +158,20 @@ public String id() {
157158
}
158159

159160
public String routing() {
160-
if (fieldsValues == null) {
161-
return null;
162-
}
163161
List<Object> values = fieldsValues.get(RoutingFieldMapper.NAME);
164162
if (values == null || values.isEmpty()) {
165163
return null;
166164
}
167165
assert values.size() == 1;
168-
return values.get(0).toString();
166+
return values.getFirst().toString();
169167
}
170168

171169
public Map<String, List<Object>> fields() {
172-
return fieldsValues != null ? fieldsValues : emptyMap();
170+
return fieldsValues;
173171
}
174172

175173
public void reset() {
176-
if (fieldsValues != null) {
177-
fieldsValues.clear();
178-
}
174+
fieldsValues.clear();
179175
source = null;
180176
id = null;
181177

@@ -186,11 +182,6 @@ public void reset() {
186182
}
187183

188184
void addValue(String name, Object value) {
189-
if (fieldsValues == null) {
190-
fieldsValues = new HashMap<>();
191-
}
192-
193-
List<Object> values = fieldsValues.computeIfAbsent(name, k -> new ArrayList<>(2));
194-
values.add(value);
185+
fieldsValues.computeIfAbsent(name, k -> new ArrayList<>(2)).add(value);
195186
}
196187
}

0 commit comments

Comments
 (0)