Skip to content

Commit 595ec8c

Browse files
authored
Remove artificial default processors limit
Today Elasticsearch limits the number of processors used in computing thread counts to 32. This was from a time when Elasticsearch created more threads than it does now and users would run into out of memory errors. It appears the real cause of these out of memory errors was not well understood (it's often due to ulimit settings) and so users were left hitting these out of memory errors on boxes with high core counts. Today Elasticsearch creates less threads (but still a lot) and we have a bootstrap check in place to ensure that the relevant ulimit is not too low. There are some caveats still to having too many concurrent indexing threads as it can lead to too many little segments, and it's not a magical go faster knob if indexing is already bottlenecked by disk, but this limitation is artificial and surprising to users and so it should be removed. This commit also increases the lower bound of the max processes ulimit, to prepare for a world where Elasticsearch instances might be running with more the previous cap of 32 processors. With the current settings, Elasticsearch wants to create roughly 576 + 25 * p / 2 threads, where p is the number of processors. Add in roughly 7 * p / 8 threads for the GC threads and a fudge factor, and 4096 should cover us pretty well up to 256 cores. Relates #20874
1 parent 7f7e99e commit 595ec8c

File tree

14 files changed

+24
-23
lines changed

14 files changed

+24
-23
lines changed

core/src/main/java/org/elasticsearch/action/search/TransportMultiSearchAction.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public TransportMultiSearchAction(Settings settings, ThreadPool threadPool, Tran
5151
super(settings, MultiSearchAction.NAME, threadPool, transportService, actionFilters, indexNameExpressionResolver, MultiSearchRequest::new);
5252
this.clusterService = clusterService;
5353
this.searchAction = searchAction;
54-
this.availableProcessors = EsExecutors.boundedNumberOfProcessors(settings);
54+
this.availableProcessors = EsExecutors.numberOfProcessors(settings);
5555
}
5656

5757
// For testing only:

core/src/main/java/org/elasticsearch/bootstrap/BootstrapCheck.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,8 @@ boolean isMemoryLocked() {
308308

309309
static class MaxNumberOfThreadsCheck implements Check {
310310

311-
private final long maxNumberOfThreadsThreshold = 1 << 11;
311+
// this should be plenty for machines up to 256 cores
312+
private final long maxNumberOfThreadsThreshold = 1 << 12;
312313

313314
@Override
314315
public boolean check() {

core/src/main/java/org/elasticsearch/common/util/PageCacheRecycler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ protected PageCacheRecycler(Settings settings) {
6969
super(settings);
7070
final Type type = TYPE_SETTING .get(settings);
7171
final long limit = LIMIT_HEAP_SETTING .get(settings).getBytes();
72-
final int availableProcessors = EsExecutors.boundedNumberOfProcessors(settings);
72+
final int availableProcessors = EsExecutors.numberOfProcessors(settings);
7373

7474
// We have a global amount of memory that we need to divide across data types.
7575
// Since some types are more useful than other ones we give them different weights.

core/src/main/java/org/elasticsearch/common/util/concurrent/EsExecutors.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,17 @@ public class EsExecutors {
4040
* This is used to adjust thread pools sizes etc. per node.
4141
*/
4242
public static final Setting<Integer> PROCESSORS_SETTING =
43-
Setting.intSetting("processors", Math.min(32, Runtime.getRuntime().availableProcessors()), 1, Property.NodeScope);
43+
Setting.intSetting("processors", Runtime.getRuntime().availableProcessors(), 1, Property.NodeScope);
4444

4545
/**
46-
* Returns the number of processors available but at most <tt>32</tt>.
46+
* Returns the number of available processors. Defaults to
47+
* {@link Runtime#availableProcessors()} but can be overridden by passing a {@link Settings}
48+
* instance with the key "processors" set to the desired value.
49+
*
50+
* @param settings a {@link Settings} instance from which to derive the available processors
51+
* @return the number of available processors
4752
*/
48-
public static int boundedNumberOfProcessors(Settings settings) {
49-
/* This relates to issues where machines with large number of cores
50-
* ie. >= 48 create too many threads and run into OOM see #3478
51-
* We just use an 32 core upper-bound here to not stress the system
52-
* too much with too many created threads */
53+
public static int numberOfProcessors(final Settings settings) {
5354
return PROCESSORS_SETTING.get(settings);
5455
}
5556

core/src/main/java/org/elasticsearch/index/MergeSchedulerConfig.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public final class MergeSchedulerConfig {
5454

5555
public static final Setting<Integer> MAX_THREAD_COUNT_SETTING =
5656
new Setting<>("index.merge.scheduler.max_thread_count",
57-
(s) -> Integer.toString(Math.max(1, Math.min(4, EsExecutors.boundedNumberOfProcessors(s) / 2))),
57+
(s) -> Integer.toString(Math.max(1, Math.min(4, EsExecutors.numberOfProcessors(s) / 2))),
5858
(s) -> Setting.parseInt(s, 1, "index.merge.scheduler.max_thread_count"), Property.Dynamic,
5959
Property.IndexScope);
6060
public static final Setting<Integer> MAX_MERGE_COUNT_SETTING =

core/src/main/java/org/elasticsearch/monitor/os/OsService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public OsService(Settings settings) {
4141
super(settings);
4242
this.probe = OsProbe.getInstance();
4343
TimeValue refreshInterval = REFRESH_INTERVAL_SETTING.get(settings);
44-
this.info = probe.osInfo(refreshInterval.millis(), EsExecutors.boundedNumberOfProcessors(settings));
44+
this.info = probe.osInfo(refreshInterval.millis(), EsExecutors.numberOfProcessors(settings));
4545
this.osStatsCache = new OsStatsCache(refreshInterval, probe.osStats());
4646
logger.debug("using refresh_interval [{}]", refreshInterval);
4747
}

core/src/main/java/org/elasticsearch/threadpool/FixedExecutorBuilder.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
import org.elasticsearch.common.settings.Settings;
2424
import org.elasticsearch.common.unit.SizeValue;
2525
import org.elasticsearch.common.util.concurrent.EsExecutors;
26-
import org.elasticsearch.common.util.concurrent.EsThreadPoolExecutor;
2726
import org.elasticsearch.common.util.concurrent.ThreadContext;
2827
import org.elasticsearch.node.Node;
2928

@@ -79,7 +78,7 @@ public FixedExecutorBuilder(final Settings settings, final String name, final in
7978

8079
private int applyHardSizeLimit(final Settings settings, final String name) {
8180
if (name.equals(ThreadPool.Names.BULK) || name.equals(ThreadPool.Names.INDEX)) {
82-
return 1 + EsExecutors.boundedNumberOfProcessors(settings);
81+
return 1 + EsExecutors.numberOfProcessors(settings);
8382
} else {
8483
return Integer.MAX_VALUE;
8584
}

core/src/main/java/org/elasticsearch/threadpool/ThreadPool.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ public ThreadPool(final Settings settings, final ExecutorBuilder<?>... customBui
163163
assert Node.NODE_NAME_SETTING.exists(settings);
164164

165165
final Map<String, ExecutorBuilder> builders = new HashMap<>();
166-
final int availableProcessors = EsExecutors.boundedNumberOfProcessors(settings);
166+
final int availableProcessors = EsExecutors.numberOfProcessors(settings);
167167
final int halfProcMaxAt5 = halfNumberOfProcessorsMaxFive(availableProcessors);
168168
final int halfProcMaxAt10 = halfNumberOfProcessorsMaxTen(availableProcessors);
169169
final int genericThreadPoolMax = boundedBy(4 * availableProcessors, 128, 512);

core/src/test/java/org/elasticsearch/threadpool/FixedThreadPoolTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public void testRejectedExecutionCounter() throws InterruptedException {
3333
final String threadPoolName = randomThreadPool(ThreadPool.ThreadPoolType.FIXED);
3434
// some of the fixed thread pool are bound by the number of
3535
// cores so we can not exceed that
36-
final int size = randomIntBetween(1, EsExecutors.boundedNumberOfProcessors(Settings.EMPTY));
36+
final int size = randomIntBetween(1, EsExecutors.numberOfProcessors(Settings.EMPTY));
3737
final int queueSize = randomIntBetween(1, 16);
3838
final long rejections = randomIntBetween(1, 16);
3939

core/src/test/java/org/elasticsearch/threadpool/UpdateThreadPoolSettingsTests.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public void testCorrectThreadPoolTypePermittedInSettings() throws InterruptedExc
6262

6363
public void testIndexingThreadPoolsMaxSize() throws InterruptedException {
6464
final String name = randomFrom(Names.BULK, Names.INDEX);
65-
final int maxSize = 1 + EsExecutors.boundedNumberOfProcessors(Settings.EMPTY);
65+
final int maxSize = 1 + EsExecutors.numberOfProcessors(Settings.EMPTY);
6666
final int tooBig = randomIntBetween(1 + maxSize, Integer.MAX_VALUE);
6767

6868
// try to create a too big thread pool
@@ -89,7 +89,7 @@ public void testIndexingThreadPoolsMaxSize() throws InterruptedException {
8989

9090
private static int getExpectedThreadPoolSize(Settings settings, String name, int size) {
9191
if (name.equals(ThreadPool.Names.BULK) || name.equals(ThreadPool.Names.INDEX)) {
92-
return Math.min(size, EsExecutors.boundedNumberOfProcessors(settings));
92+
return Math.min(size, EsExecutors.numberOfProcessors(settings));
9393
} else {
9494
return size;
9595
}
@@ -185,7 +185,7 @@ public void testCustomThreadPool() throws Exception {
185185
new ScalingExecutorBuilder(
186186
"my_pool1",
187187
1,
188-
EsExecutors.boundedNumberOfProcessors(Settings.EMPTY),
188+
EsExecutors.numberOfProcessors(Settings.EMPTY),
189189
TimeValue.timeValueMinutes(1));
190190

191191
final FixedExecutorBuilder fixed = new FixedExecutorBuilder(Settings.EMPTY, "my_pool2", 1, 1);

0 commit comments

Comments
 (0)