Skip to content

Commit 7f63891

Browse files
original-brownbearcbuescher
authored andcommitted
Make CompatibilityVersions.minimumVersions cheaper (elastic#112186)
This is a significant portion of CS updates at the moment. We should look into avoiding the computation here altogether unless the nodes change, but until then this is a trivial ~5x speedup that saves loads cluster state thread time, especially in integration tests.
1 parent 883f1fc commit 7f63891

File tree

1 file changed

+22
-15
lines changed

1 file changed

+22
-15
lines changed

server/src/main/java/org/elasticsearch/cluster/version/CompatibilityVersions.java

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,9 @@
1919

2020
import java.io.IOException;
2121
import java.util.Collection;
22-
import java.util.Comparator;
2322
import java.util.HashMap;
2423
import java.util.Map;
2524
import java.util.Objects;
26-
import java.util.stream.Collectors;
27-
import java.util.stream.Stream;
2825

2926
/**
3027
* Wraps component version numbers for cluster state
@@ -42,25 +39,35 @@ public record CompatibilityVersions(
4239
Map<String, org.elasticsearch.indices.SystemIndexDescriptor.MappingsVersion> systemIndexMappingsVersion
4340
) implements Writeable, ToXContentFragment {
4441

42+
public static final CompatibilityVersions EMPTY = new CompatibilityVersions(TransportVersions.MINIMUM_COMPATIBLE, Map.of());
43+
4544
/**
4645
* Constructs a VersionWrapper collecting all the minimum versions from the values of the map.
4746
*
4847
* @param compatibilityVersions A map of strings (typically node identifiers) and versions wrappers
4948
* @return Minimum versions for the cluster
5049
*/
5150
public static CompatibilityVersions minimumVersions(Collection<CompatibilityVersions> compatibilityVersions) {
52-
TransportVersion minimumTransport = compatibilityVersions.stream()
53-
.map(CompatibilityVersions::transportVersion)
54-
.min(Comparator.naturalOrder())
55-
// In practice transportVersions is always nonempty (except in tests) but use a conservative default anyway:
56-
.orElse(TransportVersions.MINIMUM_COMPATIBLE);
57-
58-
Map<String, SystemIndexDescriptor.MappingsVersion> minimumMappingsVersions = compatibilityVersions.stream()
59-
.flatMap(mv -> mv.systemIndexMappingsVersion().entrySet().stream())
60-
.collect(
61-
Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (v1, v2) -> Stream.of(v1, v2).min(Comparator.naturalOrder()).get())
62-
);
63-
51+
if (compatibilityVersions.isEmpty()) {
52+
return EMPTY;
53+
}
54+
TransportVersion minimumTransport = null;
55+
Map<String, SystemIndexDescriptor.MappingsVersion> minimumMappingsVersions = null;
56+
for (CompatibilityVersions cv : compatibilityVersions) {
57+
TransportVersion version = cv.transportVersion();
58+
if (minimumTransport == null) {
59+
minimumTransport = version;
60+
minimumMappingsVersions = new HashMap<>(cv.systemIndexMappingsVersion());
61+
continue;
62+
}
63+
if (version.compareTo(minimumTransport) < 0) {
64+
minimumTransport = version;
65+
}
66+
for (Map.Entry<String, SystemIndexDescriptor.MappingsVersion> entry : cv.systemIndexMappingsVersion().entrySet()) {
67+
minimumMappingsVersions.merge(entry.getKey(), entry.getValue(), (v1, v2) -> v1.compareTo(v2) < 0 ? v1 : v2);
68+
}
69+
}
70+
// transportVersions is always non-null since we break out on empty above
6471
return new CompatibilityVersions(minimumTransport, minimumMappingsVersions);
6572
}
6673

0 commit comments

Comments
 (0)