Skip to content

Commit c94f5b9

Browse files
Speed up Version Checks (#62216)
The `fromId` method would show up in profiling and JIT analysis as not-inlinable because it's too large in the contexts it's used in in many cases and was consuming a surprising amount of cycles for computing the min compat versions. -> extract cold path from `fromId` to make JIT happy and cache minimumg compatible versions to fields.
1 parent 269fe6e commit c94f5b9

File tree

1 file changed

+55
-28
lines changed

1 file changed

+55
-28
lines changed

server/src/main/java/org/elasticsearch/Version.java

+55-28
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ public class Version implements Comparable<Version>, ToXContentFragment {
121121
assert CURRENT.luceneVersion.equals(org.apache.lucene.util.Version.LATEST) : "Version must be upgraded to ["
122122
+ org.apache.lucene.util.Version.LATEST + "] is still set to [" + CURRENT.luceneVersion + "]";
123123

124+
builder.put(V_EMPTY_ID, V_EMPTY);
124125
idToVersion = builder.build();
125126
}
126127

@@ -129,36 +130,36 @@ public static Version readVersion(StreamInput in) throws IOException {
129130
}
130131

131132
public static Version fromId(int id) {
132-
if (idToVersion.containsKey(id)) {
133-
return idToVersion.get(id);
133+
final Version known = idToVersion.get(id);
134+
if (known != null) {
135+
return known;
134136
}
135-
switch (id) {
136-
case V_EMPTY_ID:
137-
return V_EMPTY;
138-
default:
139-
// We need at least the major of the Lucene version to be correct.
140-
// Our best guess is to use the same Lucene version as the previous
141-
// version in the list, assuming that it didn't change.
142-
List<Version> versions = DeclaredVersionsHolder.DECLARED_VERSIONS;
143-
Version tmp = new Version(id, org.apache.lucene.util.Version.LATEST);
144-
int index = Collections.binarySearch(versions, tmp);
145-
if (index < 0) {
146-
index = -2 - index;
147-
} else {
148-
assert false : "Version [" + tmp + "] is declared but absent from the switch statement in Version#fromId";
149-
}
150-
final org.apache.lucene.util.Version luceneVersion;
151-
if (index == -1) {
152-
// this version is older than any supported version, so we
153-
// assume it is the previous major to the oldest Lucene version
154-
// that we know about
155-
luceneVersion = org.apache.lucene.util.Version.fromBits(
156-
versions.get(0).luceneVersion.major - 1, 0, 0);
157-
} else {
158-
luceneVersion = versions.get(index).luceneVersion;
159-
}
160-
return new Version(id, luceneVersion);
137+
return fromIdSlow(id);
138+
}
139+
140+
private static Version fromIdSlow(int id) {
141+
// We need at least the major of the Lucene version to be correct.
142+
// Our best guess is to use the same Lucene version as the previous
143+
// version in the list, assuming that it didn't change.
144+
List<Version> versions = DeclaredVersionsHolder.DECLARED_VERSIONS;
145+
Version tmp = new Version(id, org.apache.lucene.util.Version.LATEST);
146+
int index = Collections.binarySearch(versions, tmp);
147+
if (index < 0) {
148+
index = -2 - index;
149+
} else {
150+
assert false : "Version [" + tmp + "] is declared but absent from the switch statement in Version#fromId";
151+
}
152+
final org.apache.lucene.util.Version luceneVersion;
153+
if (index == -1) {
154+
// this version is older than any supported version, so we
155+
// assume it is the previous major to the oldest Lucene version
156+
// that we know about
157+
luceneVersion = org.apache.lucene.util.Version.fromBits(
158+
versions.get(0).luceneVersion.major - 1, 0, 0);
159+
} else {
160+
luceneVersion = versions.get(index).luceneVersion;
161161
}
162+
return new Version(id, luceneVersion);
162163
}
163164

164165
/**
@@ -285,6 +286,14 @@ private static class DeclaredVersionsHolder {
285286
static final List<Version> DECLARED_VERSIONS = Collections.unmodifiableList(getDeclaredVersions(Version.class));
286287
}
287288

289+
// lazy initialized because we don't yet have the declared versions ready when instantiating the cached Version
290+
// instances
291+
private Version minCompatVersion;
292+
293+
// lazy initialized because we don't yet have the declared versions ready when instantiating the cached Version
294+
// instances
295+
private Version minIndexCompatVersion;
296+
288297
/**
289298
* Returns the minimum compatible version based on the current
290299
* version. Ie a node needs to have at least the return version in order
@@ -293,6 +302,15 @@ private static class DeclaredVersionsHolder {
293302
* is a beta or RC release then the version itself is returned.
294303
*/
295304
public Version minimumCompatibilityVersion() {
305+
Version res = minCompatVersion;
306+
if (res == null) {
307+
res = computeMinCompatVersion();
308+
minCompatVersion = res;
309+
}
310+
return res;
311+
}
312+
313+
private Version computeMinCompatVersion() {
296314
if (major == 6) {
297315
// force the minimum compatibility for version 6 to 5.6 since we don't reference version 5 anymore
298316
return Version.fromId(5060099);
@@ -324,6 +342,15 @@ public Version minimumCompatibilityVersion() {
324342
* code that is used to read / write file formats like transaction logs, cluster state, and index metadata.
325343
*/
326344
public Version minimumIndexCompatibilityVersion() {
345+
Version res = minIndexCompatVersion;
346+
if (res == null) {
347+
res = computeMinIndexCompatVersion();
348+
minIndexCompatVersion = res;
349+
}
350+
return res;
351+
}
352+
353+
private Version computeMinIndexCompatVersion() {
327354
final int bwcMajor;
328355
if (major == 5) {
329356
bwcMajor = 2; // we jumped from 2 to 5

0 commit comments

Comments
 (0)