Skip to content

Commit 08daa30

Browse files
committed
Return List instead of an array from settings (#26903)
Today we return a `String[]` that requires copying values for every access. Yet, we already store the setting as a list so we can also directly return the unmodifiable list directly. This makes list / array access in settings a much cheaper operation especially if lists are large.
1 parent e48d747 commit 08daa30

File tree

68 files changed

+325
-333
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+325
-333
lines changed

core/src/main/java/org/elasticsearch/cluster/routing/allocation/decider/AwarenessAllocationDecider.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
package org.elasticsearch.cluster.routing.allocation.decider;
2121

2222
import java.util.HashMap;
23+
import java.util.List;
2324
import java.util.Map;
2425

2526
import com.carrotsearch.hppc.ObjectIntHashMap;
@@ -85,7 +86,7 @@ public class AwarenessAllocationDecider extends AllocationDecider {
8586

8687
private volatile String[] awarenessAttributes;
8788

88-
private volatile Map<String, String[]> forcedAwarenessAttributes;
89+
private volatile Map<String, List<String>> forcedAwarenessAttributes;
8990

9091
public AwarenessAllocationDecider(Settings settings, ClusterSettings clusterSettings) {
9192
super(settings);
@@ -97,11 +98,11 @@ public AwarenessAllocationDecider(Settings settings, ClusterSettings clusterSett
9798
}
9899

99100
private void setForcedAwarenessAttributes(Settings forceSettings) {
100-
Map<String, String[]> forcedAwarenessAttributes = new HashMap<>();
101+
Map<String, List<String>> forcedAwarenessAttributes = new HashMap<>();
101102
Map<String, Settings> forceGroups = forceSettings.getAsGroups();
102103
for (Map.Entry<String, Settings> entry : forceGroups.entrySet()) {
103-
String[] aValues = entry.getValue().getAsArray("values");
104-
if (aValues.length > 0) {
104+
List<String> aValues = entry.getValue().getAsList("values");
105+
if (aValues.size() > 0) {
105106
forcedAwarenessAttributes.put(entry.getKey(), aValues);
106107
}
107108
}
@@ -169,7 +170,7 @@ private Decision underCapacity(ShardRouting shardRouting, RoutingNode node, Rout
169170
}
170171

171172
int numberOfAttributes = nodesPerAttribute.size();
172-
String[] fullValues = forcedAwarenessAttributes.get(awarenessAttribute);
173+
List<String> fullValues = forcedAwarenessAttributes.get(awarenessAttribute);
173174
if (fullValues != null) {
174175
for (String fullValue : fullValues) {
175176
if (!shardPerAttribute.containsKey(fullValue)) {

core/src/main/java/org/elasticsearch/common/settings/Setting.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -804,14 +804,14 @@ private static class ListSetting<T> extends Setting<List<T>> {
804804

805805
private ListSetting(String key, Function<Settings, List<String>> defaultStringValue, Function<String, List<T>> parser,
806806
Property... properties) {
807-
super(new ListKey(key), (s) -> Setting.arrayToParsableString(defaultStringValue.apply(s).toArray(Strings.EMPTY_ARRAY)), parser,
807+
super(new ListKey(key), (s) -> Setting.arrayToParsableString(defaultStringValue.apply(s)), parser,
808808
properties);
809809
this.defaultStringValue = defaultStringValue;
810810
}
811811

812812
@Override
813813
public String getRaw(Settings settings) {
814-
String[] array = settings.getAsArray(getKey(), null);
814+
List<String> array = settings.getAsList(getKey(), null);
815815
return array == null ? defaultValue.apply(settings) : arrayToParsableString(array);
816816
}
817817

@@ -823,11 +823,11 @@ boolean hasComplexMatcher() {
823823
@Override
824824
public void diff(Settings.Builder builder, Settings source, Settings defaultSettings) {
825825
if (exists(source) == false) {
826-
String[] asArray = defaultSettings.getAsArray(getKey(), null);
827-
if (asArray == null) {
828-
builder.putArray(getKey(), defaultStringValue.apply(defaultSettings));
826+
List<String> asList = defaultSettings.getAsList(getKey(), null);
827+
if (asList == null) {
828+
builder.putList(getKey(), defaultStringValue.apply(defaultSettings));
829829
} else {
830-
builder.putArray(getKey(), asArray);
830+
builder.putList(getKey(), asList);
831831
}
832832
}
833833
}
@@ -1087,7 +1087,7 @@ private static List<String> parseableStringToList(String parsableString) {
10871087
}
10881088
}
10891089

1090-
private static String arrayToParsableString(String[] array) {
1090+
private static String arrayToParsableString(List<String> array) {
10911091
try {
10921092
XContentBuilder builder = XContentBuilder.builder(XContentType.JSON.xContent());
10931093
builder.startArray();

core/src/main/java/org/elasticsearch/common/settings/Settings.java

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -396,48 +396,48 @@ public SizeValue getAsSize(String setting, SizeValue defaultValue) throws Settin
396396
}
397397

398398
/**
399-
* The values associated with a setting key as an array.
399+
* The values associated with a setting key as an immutable list.
400400
* <p>
401401
* It will also automatically load a comma separated list under the settingPrefix and merge with
402402
* the numbered format.
403403
*
404-
* @param key The setting prefix to load the array by
405-
* @return The setting array values
404+
* @param key The setting key to load the list by
405+
* @return The setting list values
406406
*/
407-
public String[] getAsArray(String key) throws SettingsException {
408-
return getAsArray(key, Strings.EMPTY_ARRAY, true);
407+
public List<String> getAsList(String key) throws SettingsException {
408+
return getAsList(key, Collections.emptyList());
409409
}
410410

411411
/**
412-
* The values associated with a setting key as an array.
412+
* The values associated with a setting key as an immutable list.
413413
* <p>
414414
* If commaDelimited is true, it will automatically load a comma separated list under the settingPrefix and merge with
415415
* the numbered format.
416416
*
417-
* @param key The setting key to load the array by
418-
* @return The setting array values
417+
* @param key The setting key to load the list by
418+
* @return The setting list values
419419
*/
420-
public String[] getAsArray(String key, String[] defaultArray) throws SettingsException {
421-
return getAsArray(key, defaultArray, true);
420+
public List<String> getAsList(String key, List<String> defaultValue) throws SettingsException {
421+
return getAsList(key, defaultValue, true);
422422
}
423423

424424
/**
425-
* The values associated with a setting key as an array.
425+
* The values associated with a setting key as an immutable list.
426426
* <p>
427427
* It will also automatically load a comma separated list under the settingPrefix and merge with
428428
* the numbered format.
429429
*
430-
* @param key The setting key to load the array by
431-
* @param defaultArray The default array to use if no value is specified
430+
* @param key The setting key to load the list by
431+
* @param defaultValue The default value to use if no value is specified
432432
* @param commaDelimited Whether to try to parse a string as a comma-delimited value
433-
* @return The setting array values
433+
* @return The setting list values
434434
*/
435-
public String[] getAsArray(String key, String[] defaultArray, Boolean commaDelimited) throws SettingsException {
435+
public List<String> getAsList(String key, List<String> defaultValue, Boolean commaDelimited) throws SettingsException {
436436
List<String> result = new ArrayList<>();
437437
final Object valueFromPrefix = settings.get(key);
438438
if (valueFromPrefix != null) {
439439
if (valueFromPrefix instanceof List) {
440-
result = ((List<String>) valueFromPrefix);
440+
return ((List<String>) valueFromPrefix); // it's already unmodifiable since the builder puts it as a such
441441
} else if (commaDelimited) {
442442
String[] strings = Strings.splitStringByCommaToArray(get(key));
443443
if (strings.length > 0) {
@@ -451,9 +451,9 @@ public String[] getAsArray(String key, String[] defaultArray, Boolean commaDelim
451451
}
452452

453453
if (result.isEmpty()) {
454-
return defaultArray;
454+
return defaultValue;
455455
}
456-
return result.toArray(new String[result.size()]);
456+
return Collections.unmodifiableList(result);
457457
}
458458

459459

@@ -582,7 +582,7 @@ public static Settings readSettingsFromStream(StreamInput in) throws IOException
582582
if (value == null) {
583583
builder.putNull(key);
584584
} else if (value instanceof List) {
585-
builder.putArray(key, (List<String>) value);
585+
builder.putList(key, (List<String>) value);
586586
} else {
587587
builder.put(key, value.toString());
588588
}
@@ -709,7 +709,7 @@ private static void fromXContent(XContentParser parser, StringBuilder keyBuilder
709709
}
710710
String key = keyBuilder.toString();
711711
validateValue(key, list, builder, parser, allowNullValues);
712-
builder.putArray(key, list);
712+
builder.putList(key, list);
713713
} else if (parser.currentToken() == XContentParser.Token.VALUE_NULL) {
714714
String key = keyBuilder.toString();
715715
validateValue(key, null, builder, parser, allowNullValues);
@@ -928,7 +928,7 @@ public Builder copy(String key, String sourceKey, Settings source) {
928928
}
929929
final Object value = source.settings.get(sourceKey);
930930
if (value instanceof List) {
931-
return putArray(key, (List)value);
931+
return putList(key, (List)value);
932932
} else if (value == null) {
933933
return putNull(key);
934934
} else {
@@ -1052,8 +1052,8 @@ public Builder put(String setting, long value, ByteSizeUnit sizeUnit) {
10521052
* @param values The values
10531053
* @return The builder
10541054
*/
1055-
public Builder putArray(String setting, String... values) {
1056-
return putArray(setting, Arrays.asList(values));
1055+
public Builder putList(String setting, String... values) {
1056+
return putList(setting, Arrays.asList(values));
10571057
}
10581058

10591059
/**
@@ -1063,7 +1063,7 @@ public Builder putArray(String setting, String... values) {
10631063
* @param values The values
10641064
* @return The builder
10651065
*/
1066-
public Builder putArray(String setting, List<String> values) {
1066+
public Builder putList(String setting, List<String> values) {
10671067
remove(setting);
10681068
map.put(setting, Collections.unmodifiableList(new ArrayList<>(values)));
10691069
return this;

core/src/main/java/org/elasticsearch/env/Environment.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ public Environment(final Settings settings, final Path configPath) {
153153
Settings.Builder finalSettings = Settings.builder().put(settings);
154154
finalSettings.put(PATH_HOME_SETTING.getKey(), homeFile);
155155
if (PATH_DATA_SETTING.exists(settings)) {
156-
finalSettings.putArray(PATH_DATA_SETTING.getKey(), dataPaths);
156+
finalSettings.putList(PATH_DATA_SETTING.getKey(), dataPaths);
157157
}
158158
finalSettings.put(PATH_LOGS_SETTING.getKey(), logsFile.toString());
159159
this.settings = finalSettings.build();

core/src/main/java/org/elasticsearch/index/analysis/Analysis.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@
7171
import java.nio.file.Files;
7272
import java.nio.file.Path;
7373
import java.util.ArrayList;
74-
import java.util.Arrays;
7574
import java.util.Collection;
7675
import java.util.HashMap;
7776
import java.util.List;
@@ -110,10 +109,10 @@ public static CharArraySet parseStemExclusion(Settings settings, CharArraySet de
110109
if ("_none_".equals(value)) {
111110
return CharArraySet.EMPTY_SET;
112111
}
113-
String[] stemExclusion = settings.getAsArray("stem_exclusion", null);
112+
List<String> stemExclusion = settings.getAsList("stem_exclusion", null);
114113
if (stemExclusion != null) {
115114
// LUCENE 4 UPGRADE: Should be settings.getAsBoolean("stem_exclusion_case", false)?
116-
return new CharArraySet(Arrays.asList(stemExclusion), false);
115+
return new CharArraySet(stemExclusion, false);
117116
} else {
118117
return defaultStemExclusion;
119118
}
@@ -166,7 +165,7 @@ public static CharArraySet parseWords(Environment env, Settings settings, String
166165
if ("_none_".equals(value)) {
167166
return CharArraySet.EMPTY_SET;
168167
} else {
169-
return resolveNamedWords(Arrays.asList(settings.getAsArray(name)), namedWords, ignoreCase);
168+
return resolveNamedWords(settings.getAsList(name), namedWords, ignoreCase);
170169
}
171170
}
172171
List<String> pathLoadedWords = getWordList(env, settings, name);
@@ -233,11 +232,11 @@ public static List<String> getWordList(Environment env, Settings settings, Strin
233232
String wordListPath = settings.get(settingPrefix + "_path", null);
234233

235234
if (wordListPath == null) {
236-
String[] explicitWordList = settings.getAsArray(settingPrefix, null);
235+
List<String> explicitWordList = settings.getAsList(settingPrefix, null);
237236
if (explicitWordList == null) {
238237
return null;
239238
} else {
240-
return Arrays.asList(explicitWordList);
239+
return explicitWordList;
241240
}
242241
}
243242

core/src/main/java/org/elasticsearch/index/analysis/AnalysisRegistry.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,7 @@ private void processAnalyzerFactory(DeprecationLogger deprecationLogger,
571571
// the setting is now removed but we only support it for loading indices created before v5.0
572572
deprecationLogger.deprecated("setting [{}] is only allowed on index [{}] because it was created before 5.x; " +
573573
"analyzer aliases can no longer be created on new indices.", analyzerAliasKey, indexSettings.getIndex().getName());
574-
Set<String> aliases = Sets.newHashSet(indexSettings.getSettings().getAsArray(analyzerAliasKey));
574+
Set<String> aliases = Sets.newHashSet(indexSettings.getSettings().getAsList(analyzerAliasKey));
575575
for (String alias : aliases) {
576576
if (analyzerAliases.putIfAbsent(alias, analyzer) != null) {
577577
throw new IllegalStateException("alias [" + alias + "] is already used by [" + analyzerAliases.get(alias).name() + "]");

core/src/main/java/org/elasticsearch/index/analysis/CustomAnalyzerProvider.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ public void build(final Map<String, TokenizerFactory> tokenizers, final Map<Stri
5858
throw new IllegalArgumentException("Custom Analyzer [" + name() + "] failed to find tokenizer under name [" + tokenizerName + "]");
5959
}
6060

61-
String[] charFilterNames = analyzerSettings.getAsArray("char_filter");
62-
List<CharFilterFactory> charFiltersList = new ArrayList<>(charFilterNames.length);
61+
List<String> charFilterNames = analyzerSettings.getAsList("char_filter");
62+
List<CharFilterFactory> charFiltersList = new ArrayList<>(charFilterNames.size());
6363
for (String charFilterName : charFilterNames) {
6464
CharFilterFactory charFilter = charFilters.get(charFilterName);
6565
if (charFilter == null) {
@@ -74,8 +74,8 @@ public void build(final Map<String, TokenizerFactory> tokenizers, final Map<Stri
7474

7575
int offsetGap = analyzerSettings.getAsInt("offset_gap", -1);
7676

77-
String[] tokenFilterNames = analyzerSettings.getAsArray("filter");
78-
List<TokenFilterFactory> tokenFilterList = new ArrayList<>(tokenFilterNames.length);
77+
List<String> tokenFilterNames = analyzerSettings.getAsList("filter");
78+
List<TokenFilterFactory> tokenFilterList = new ArrayList<>(tokenFilterNames.size());
7979
for (String tokenFilterName : tokenFilterNames) {
8080
TokenFilterFactory tokenFilter = tokenFilters.get(tokenFilterName);
8181
if (tokenFilter == null) {

core/src/main/java/org/elasticsearch/index/analysis/CustomNormalizerProvider.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ public void build(final TokenizerFactory keywordTokenizerFactory, final Map<Stri
5050
throw new IllegalArgumentException("Custom normalizer [" + name() + "] cannot configure a tokenizer");
5151
}
5252

53-
String[] charFilterNames = analyzerSettings.getAsArray("char_filter");
54-
List<CharFilterFactory> charFiltersList = new ArrayList<>(charFilterNames.length);
53+
List<String> charFilterNames = analyzerSettings.getAsList("char_filter");
54+
List<CharFilterFactory> charFiltersList = new ArrayList<>(charFilterNames.size());
5555
for (String charFilterName : charFilterNames) {
5656
CharFilterFactory charFilter = charFilters.get(charFilterName);
5757
if (charFilter == null) {
@@ -66,8 +66,8 @@ public void build(final TokenizerFactory keywordTokenizerFactory, final Map<Stri
6666
charFiltersList.add(charFilter);
6767
}
6868

69-
String[] tokenFilterNames = analyzerSettings.getAsArray("filter");
70-
List<TokenFilterFactory> tokenFilterList = new ArrayList<>(tokenFilterNames.length);
69+
List<String> tokenFilterNames = analyzerSettings.getAsList("filter");
70+
List<TokenFilterFactory> tokenFilterList = new ArrayList<>(tokenFilterNames.size());
7171
for (String tokenFilterName : tokenFilterNames) {
7272
TokenFilterFactory tokenFilter = tokenFilters.get(tokenFilterName);
7373
if (tokenFilter == null) {

core/src/main/java/org/elasticsearch/index/analysis/EdgeNGramTokenizerFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public EdgeNGramTokenizerFactory(IndexSettings indexSettings, Environment enviro
4141
super(indexSettings, name, settings);
4242
this.minGram = settings.getAsInt("min_gram", NGramTokenizer.DEFAULT_MIN_NGRAM_SIZE);
4343
this.maxGram = settings.getAsInt("max_gram", NGramTokenizer.DEFAULT_MAX_NGRAM_SIZE);
44-
this.matcher = parseTokenChars(settings.getAsArray("token_chars"));
44+
this.matcher = parseTokenChars(settings.getAsList("token_chars"));
4545
}
4646

4747
@Override

core/src/main/java/org/elasticsearch/index/analysis/NGramTokenizerFactory.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import java.lang.reflect.Field;
2929
import java.lang.reflect.Modifier;
3030
import java.util.HashMap;
31+
import java.util.List;
3132
import java.util.Locale;
3233
import java.util.Map;
3334

@@ -65,8 +66,8 @@ public class NGramTokenizerFactory extends AbstractTokenizerFactory {
6566
MATCHERS = unmodifiableMap(matchers);
6667
}
6768

68-
static CharMatcher parseTokenChars(String[] characterClasses) {
69-
if (characterClasses == null || characterClasses.length == 0) {
69+
static CharMatcher parseTokenChars(List<String> characterClasses) {
70+
if (characterClasses == null || characterClasses.isEmpty()) {
7071
return null;
7172
}
7273
CharMatcher.Builder builder = new CharMatcher.Builder();
@@ -85,7 +86,7 @@ public NGramTokenizerFactory(IndexSettings indexSettings, Environment environmen
8586
super(indexSettings, name, settings);
8687
this.minGram = settings.getAsInt("min_gram", NGramTokenizer.DEFAULT_MIN_NGRAM_SIZE);
8788
this.maxGram = settings.getAsInt("max_gram", NGramTokenizer.DEFAULT_MAX_NGRAM_SIZE);
88-
this.matcher = parseTokenChars(settings.getAsArray("token_chars"));
89+
this.matcher = parseTokenChars(settings.getAsList("token_chars"));
8990
}
9091

9192
@Override

core/src/main/java/org/elasticsearch/index/analysis/SynonymTokenFilterFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ public TokenStream create(TokenStream tokenStream) {
9191

9292
protected Reader getRulesFromSettings(Environment env) {
9393
Reader rulesReader;
94-
if (settings.getAsArray("synonyms", null) != null) {
94+
if (settings.getAsList("synonyms", null) != null) {
9595
List<String> rulesList = Analysis.getWordList(env, settings, "synonyms");
9696
StringBuilder sb = new StringBuilder();
9797
for (String line : rulesList) {

core/src/test/java/org/elasticsearch/action/admin/indices/TransportAnalyzeActionTests.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@
4141
import org.elasticsearch.indices.analysis.AnalysisModule.AnalysisProvider;
4242
import org.elasticsearch.indices.analysis.AnalysisModuleTests.AppendCharFilter;
4343
import org.elasticsearch.plugins.AnalysisPlugin;
44-
import static org.elasticsearch.plugins.AnalysisPlugin.requriesAnalysisSettings;
4544
import org.elasticsearch.test.ESTestCase;
4645
import org.elasticsearch.test.IndexSettingsModule;
4746

@@ -74,7 +73,7 @@ public void setUp() throws Exception {
7473
.put("index.analysis.analyzer.custom_analyzer.tokenizer", "standard")
7574
.put("index.analysis.analyzer.custom_analyzer.filter", "mock")
7675
.put("index.analysis.normalizer.my_normalizer.type", "custom")
77-
.putArray("index.analysis.normalizer.my_normalizer.filter", "lowercase").build();
76+
.putList("index.analysis.normalizer.my_normalizer.filter", "lowercase").build();
7877
IndexSettings idxSettings = IndexSettingsModule.newIndexSettings("index", indexSettings);
7978
environment = new Environment(settings);
8079
AnalysisPlugin plugin = new AnalysisPlugin() {

core/src/test/java/org/elasticsearch/action/termvectors/AbstractTermVectorsTestCase.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ protected void createIndexBasedOnFieldSettings(String index, String alias, TestF
210210
Settings.Builder settings = Settings.builder()
211211
.put(indexSettings())
212212
.put("index.analysis.analyzer.tv_test.tokenizer", "standard")
213-
.putArray("index.analysis.analyzer.tv_test.filter", "lowercase");
213+
.putList("index.analysis.analyzer.tv_test.filter", "lowercase");
214214
assertAcked(prepareCreate(index).addMapping("type1", mappingBuilder).setSettings(settings).addAlias(new Alias(alias)));
215215
}
216216

0 commit comments

Comments
 (0)