Skip to content

Commit e0a81f7

Browse files
Speed up Version Checks (#62216) (#62253)
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 39e59d6 commit e0a81f7

File tree

1 file changed

+57
-31
lines changed

1 file changed

+57
-31
lines changed

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

+57-31
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ public class Version implements Comparable<Version>, ToXContentFragment {
188188
assert CURRENT.luceneVersion.equals(org.apache.lucene.util.Version.LATEST) : "Version must be upgraded to ["
189189
+ org.apache.lucene.util.Version.LATEST + "] is still set to [" + CURRENT.luceneVersion + "]";
190190

191+
builder.put(V_EMPTY_ID, V_EMPTY);
191192
idToVersion = builder.build();
192193
}
193194

@@ -196,39 +197,38 @@ public static Version readVersion(StreamInput in) throws IOException {
196197
}
197198

198199
public static Version fromId(int id) {
199-
if (idToVersion.containsKey(id)) {
200-
return idToVersion.get(id);
200+
final Version known = idToVersion.get(id);
201+
if (known != null) {
202+
return known;
201203
}
202-
switch (id) {
203-
204-
case V_EMPTY_ID:
205-
return V_EMPTY;
206-
default:
207-
// We need at least the major of the Lucene version to be correct.
208-
// Our best guess is to use the same Lucene version as the previous
209-
// version in the list, assuming that it didn't change. This is at
210-
// least correct for patch versions of known minors since we never
211-
// update the Lucene dependency for patch versions.
212-
List<Version> versions = DeclaredVersionsHolder.DECLARED_VERSIONS;
213-
Version tmp = new Version(id, org.apache.lucene.util.Version.LATEST);
214-
int index = Collections.binarySearch(versions, tmp);
215-
if (index < 0) {
216-
index = -2 - index;
217-
} else {
218-
assert false : "Version [" + tmp + "] is declared but absent from the switch statement in Version#fromId";
219-
}
220-
final org.apache.lucene.util.Version luceneVersion;
221-
if (index == -1) {
222-
// this version is older than any supported version, so we
223-
// assume it is the previous major to the oldest Lucene version
224-
// that we know about
225-
luceneVersion = org.apache.lucene.util.Version.fromBits(
226-
versions.get(0).luceneVersion.major - 1, 0, 0);
227-
} else {
228-
luceneVersion = versions.get(index).luceneVersion;
229-
}
230-
return new Version(id, luceneVersion);
204+
return fromIdSlow(id);
205+
}
206+
207+
private static Version fromIdSlow(int id) {
208+
// We need at least the major of the Lucene version to be correct.
209+
// Our best guess is to use the same Lucene version as the previous
210+
// version in the list, assuming that it didn't change. This is at
211+
// least correct for patch versions of known minors since we never
212+
// update the Lucene dependency for patch versions.
213+
List<Version> versions = DeclaredVersionsHolder.DECLARED_VERSIONS;
214+
Version tmp = new Version(id, org.apache.lucene.util.Version.LATEST);
215+
int index = Collections.binarySearch(versions, tmp);
216+
if (index < 0) {
217+
index = -2 - index;
218+
} else {
219+
assert false : "Version [" + tmp + "] is declared but absent from the switch statement in Version#fromId";
220+
}
221+
final org.apache.lucene.util.Version luceneVersion;
222+
if (index == -1) {
223+
// this version is older than any supported version, so we
224+
// assume it is the previous major to the oldest Lucene version
225+
// that we know about
226+
luceneVersion = org.apache.lucene.util.Version.fromBits(
227+
versions.get(0).luceneVersion.major - 1, 0, 0);
228+
} else {
229+
luceneVersion = versions.get(index).luceneVersion;
231230
}
231+
return new Version(id, luceneVersion);
232232
}
233233

234234
/**
@@ -373,6 +373,14 @@ private static class DeclaredVersionsHolder {
373373
static final List<Version> DECLARED_VERSIONS = Collections.unmodifiableList(getDeclaredVersions(Version.class));
374374
}
375375

376+
// lazy initialized because we don't yet have the declared versions ready when instantiating the cached Version
377+
// instances
378+
private Version minCompatVersion;
379+
380+
// lazy initialized because we don't yet have the declared versions ready when instantiating the cached Version
381+
// instances
382+
private Version minIndexCompatVersion;
383+
376384
/**
377385
* Returns the minimum compatible version based on the current
378386
* version. Ie a node needs to have at least the return version in order
@@ -381,6 +389,15 @@ private static class DeclaredVersionsHolder {
381389
* is a beta or RC release then the version itself is returned.
382390
*/
383391
public Version minimumCompatibilityVersion() {
392+
Version res = minCompatVersion;
393+
if (res == null) {
394+
res = computeMinCompatVersion();
395+
minCompatVersion = res;
396+
}
397+
return res;
398+
}
399+
400+
private Version computeMinCompatVersion() {
384401
if (major == 6) {
385402
// force the minimum compatibility for version 6 to 5.6 since we don't reference version 5 anymore
386403
return Version.fromId(5060099);
@@ -409,6 +426,15 @@ public Version minimumCompatibilityVersion() {
409426
* code that is used to read / write file formats like transaction logs, cluster state, and index metadata.
410427
*/
411428
public Version minimumIndexCompatibilityVersion() {
429+
Version res = minIndexCompatVersion;
430+
if (res == null) {
431+
res = computeMinIndexCompatVersion();
432+
minIndexCompatVersion = res;
433+
}
434+
return res;
435+
}
436+
437+
private Version computeMinIndexCompatVersion() {
412438
final int bwcMajor;
413439
if (major == 5) {
414440
bwcMajor = 2; // we jumped from 2 to 5

0 commit comments

Comments
 (0)