Skip to content

Commit 86b8063

Browse files
Optimize DataTierAllocationDecider Further (#78235)
This decider is still by far the most expensive component of reroute operations. Optimizing away some more costly allocations and slow stream loops.
1 parent ce4b95e commit 86b8063

File tree

2 files changed

+28
-25
lines changed

2 files changed

+28
-25
lines changed

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/cluster/routing/allocation/DataTierAllocationDecider.java

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,13 @@
2626
import org.elasticsearch.xpack.core.DataTier;
2727
import org.elasticsearch.xpack.core.searchablesnapshots.SearchableSnapshotsConstants;
2828

29-
import java.util.Arrays;
3029
import java.util.Collection;
3130
import java.util.Iterator;
3231
import java.util.List;
3332
import java.util.Map;
3433
import java.util.Optional;
3534
import java.util.Set;
3635
import java.util.function.Function;
37-
import java.util.stream.Collectors;
3836

3937
import static org.elasticsearch.xpack.core.DataTier.DATA_FROZEN;
4038

@@ -55,11 +53,11 @@ public class DataTierAllocationDecider extends AllocationDecider {
5553

5654
private static void validateTierSetting(String setting) {
5755
if (Strings.hasText(setting)) {
58-
Set<String> invalidTiers = Arrays.stream(setting.split(","))
59-
.filter(tier -> DataTier.validTierName(tier) == false)
60-
.collect(Collectors.toSet());
61-
if (invalidTiers.size() > 0) {
62-
throw new IllegalArgumentException("invalid tier names: " + invalidTiers);
56+
for (String s : setting.split(",")) {
57+
if (DataTier.validTierName(s) == false) {
58+
throw new IllegalArgumentException(
59+
"invalid tier names found in [" + setting + "] allowed values are " + DataTier.ALL_DATA_TIERS);
60+
}
6361
}
6462
}
6563
}
@@ -90,8 +88,7 @@ public void validate(String value, Map<Setting<?>, Object> settings, boolean exi
9088
"] tier preference may be used for partial searchable snapshots (got: [" + value + "])");
9189
}
9290
} else {
93-
String[] split = value.split(",");
94-
if (Arrays.stream(split).anyMatch(DATA_FROZEN::equals)) {
91+
if (value.contains(DATA_FROZEN)) {
9592
throw new IllegalArgumentException("[" + DATA_FROZEN + "] tier can only be used for partial searchable snapshots");
9693
}
9794
}
@@ -180,27 +177,32 @@ private Decision shouldIndexPreferTier(IndexMetadata indexMetadata, Set<Discover
180177
* {@code Optional<String>}.
181178
*/
182179
public static Optional<String> preferredAvailableTier(String prioritizedTiers, DiscoveryNodes nodes) {
183-
String[] tiers = parseTierList(prioritizedTiers);
184-
return Arrays.stream(tiers).filter(tier -> tierNodesPresent(tier, nodes)).findFirst();
180+
for (String tier : parseTierList(prioritizedTiers)) {
181+
if (tierNodesPresent(tier, nodes)) {
182+
return Optional.of(tier);
183+
}
184+
}
185+
return Optional.empty();
185186
}
186187

187188
public static String[] parseTierList(String tiers) {
188189
if (Strings.hasText(tiers) == false) {
189190
// avoid parsing overhead in the null/empty string case
190191
return Strings.EMPTY_ARRAY;
191192
} else {
192-
return Strings.tokenizeToStringArray(tiers, ",");
193+
return tiers.split(",");
193194
}
194195
}
195196

196197
static boolean tierNodesPresent(String singleTier, DiscoveryNodes nodes) {
197198
assert singleTier.equals(DiscoveryNodeRole.DATA_ROLE.roleName()) || DataTier.validTierName(singleTier) :
198199
"tier " + singleTier + " is an invalid tier name";
199200
for (ObjectCursor<DiscoveryNode> node : nodes.getNodes().values()) {
200-
if (node.value.getRoles().stream()
201-
.map(DiscoveryNodeRole::roleName)
202-
.anyMatch(s -> s.equals(DiscoveryNodeRole.DATA_ROLE.roleName()) || s.equals(singleTier))) {
203-
return true;
201+
for (DiscoveryNodeRole discoveryNodeRole : node.value.getRoles()) {
202+
String s = discoveryNodeRole.roleName();
203+
if (s.equals(DiscoveryNodeRole.DATA_ROLE.roleName()) || s.equals(singleTier)) {
204+
return true;
205+
}
204206
}
205207
}
206208
return false;

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/DataTier.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616
import org.elasticsearch.index.shard.IndexSettingProvider;
1717
import org.elasticsearch.xpack.cluster.routing.allocation.DataTierAllocationDecider;
1818

19-
import java.util.Arrays;
20-
import java.util.HashSet;
2119
import java.util.List;
2220
import java.util.Set;
2321
import java.util.stream.Collectors;
@@ -39,8 +37,15 @@ public class DataTier {
3937
public static final String DATA_COLD = "data_cold";
4038
public static final String DATA_FROZEN = "data_frozen";
4139

42-
public static final Set<String> ALL_DATA_TIERS =
43-
new HashSet<>(Arrays.asList(DATA_CONTENT, DATA_HOT, DATA_WARM, DATA_COLD, DATA_FROZEN));
40+
public static final Set<String> ALL_DATA_TIERS = Set.of(DATA_CONTENT, DATA_HOT, DATA_WARM, DATA_COLD, DATA_FROZEN);
41+
42+
static {
43+
for (String tier : ALL_DATA_TIERS) {
44+
assert tier.equals(DATA_FROZEN) || tier.contains(DATA_FROZEN) == false
45+
: "can't have two tier names containing [" + DATA_FROZEN + "] because it would break setting validation optimizations" +
46+
" in the data tier allocation decider";
47+
}
48+
}
4449

4550
// Represents an ordered list of data tiers from frozen to hot (or slow to fast)
4651
private static final List<String> ORDERED_FROZEN_TO_HOT_TIERS =
@@ -50,11 +55,7 @@ public class DataTier {
5055
* Returns true if the given tier name is a valid tier
5156
*/
5257
public static boolean validTierName(String tierName) {
53-
return DATA_CONTENT.equals(tierName) ||
54-
DATA_HOT.equals(tierName) ||
55-
DATA_WARM.equals(tierName) ||
56-
DATA_COLD.equals(tierName) ||
57-
DATA_FROZEN.equals(tierName);
58+
return ALL_DATA_TIERS.contains(tierName);
5859
}
5960

6061
/**

0 commit comments

Comments
 (0)