@@ -458,7 +458,7 @@ private ExecutorHolder rebuild(String name, ExecutorHolder previousExecutorHolde
458458 if (ThreadPoolType .FIXED == previousInfo .getThreadPoolType ()) {
459459 SizeValue updatedQueueSize = getAsSizeOrUnbounded (settings , "capacity" , getAsSizeOrUnbounded (settings , "queue" , getAsSizeOrUnbounded (settings , "queue_size" , previousInfo .getQueueSize ())));
460460 if (Objects .equals (previousInfo .getQueueSize (), updatedQueueSize )) {
461- int updatedSize = settings .getAsInt ("size" , previousInfo .getMax ());
461+ int updatedSize = applyHardSizeLimit ( name , settings .getAsInt ("size" , previousInfo .getMax () ));
462462 if (previousInfo .getMax () != updatedSize ) {
463463 logger .debug ("updating thread_pool [{}], type [{}], size [{}], queue_size [{}]" , name , type , updatedSize , updatedQueueSize );
464464 // if you think this code is crazy: that's because it is!
@@ -480,7 +480,7 @@ private ExecutorHolder rebuild(String name, ExecutorHolder previousExecutorHolde
480480 defaultQueueSize = previousInfo .getQueueSize ();
481481 }
482482
483- int size = settings .getAsInt ("size" , defaultSize );
483+ int size = applyHardSizeLimit ( name , settings .getAsInt ("size" , defaultSize ) );
484484 SizeValue queueSize = getAsSizeOrUnbounded (settings , "capacity" , getAsSizeOrUnbounded (settings , "queue" , getAsSizeOrUnbounded (settings , "queue_size" , defaultQueueSize )));
485485 logger .debug ("creating thread_pool [{}], type [{}], size [{}], queue_size [{}]" , name , type , size , queueSize );
486486 Executor executor = EsExecutors .newFixed (name , size , queueSize == null ? -1 : (int ) queueSize .singles (), threadFactory );
@@ -533,6 +533,20 @@ private ExecutorHolder rebuild(String name, ExecutorHolder previousExecutorHolde
533533 throw new IllegalArgumentException ("No type found [" + type + "], for [" + name + "]" );
534534 }
535535
536+ private int applyHardSizeLimit (String name , int requestedSize ) {
537+ int availableProcessors = EsExecutors .boundedNumberOfProcessors (settings );
538+ if (name .equals (Names .BULK ) || name .equals (Names .INDEX )) {
539+ // We use a hard max size for the indexing pools, because if too many threads enter Lucene's IndexWriter, it means
540+ // too many segments written, too frequently, too much merging, etc:
541+
542+ // TODO: I would love to be loud here (throw an exception if you ask for a too-big size), but I think this is dangerous
543+ // because on upgrade this setting could be in cluster state and hard for the user to correct?
544+ return Math .min (requestedSize , availableProcessors );
545+ } else {
546+ return requestedSize ;
547+ }
548+ }
549+
536550 private void updateSettings (Settings settings ) {
537551 Map <String , Settings > groupSettings = settings .getAsGroups ();
538552 if (groupSettings .isEmpty ()) {
0 commit comments