Skip to content

Commit ff6607d

Browse files
author
Ishan Chattopadhyaya
committed
SOLR-13350: Multithreaded search (closes #2248)
1 parent b63e9cf commit ff6607d

File tree

19 files changed

+772
-46
lines changed

19 files changed

+772
-46
lines changed

solr/CHANGES.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ Other Changes
9898
================== 9.7.0 ==================
9999
New Features
100100
---------------------
101-
(No changes)
101+
* SOLR-13350: Multithreaded search execution (Ishan Chattopadhyaya, Mark Miller, Christine Poerschke, David Smiley, noble)
102102

103103
Improvements
104104
---------------------

solr/bin/solr

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1441,6 +1441,9 @@ if [ $# -gt 0 ]; then
14411441
done
14421442
fi
14431443

1444+
# Setting number of threads for search
1445+
if ! command -v nproc &> /dev/null; then echo "Couldn't determine number of CPUs, using default number of search threads"; else cpus=`nproc`; SCRIPT_SOLR_OPTS+="-Dsolr.searchThreads=$cpus"; fi
1446+
14441447
# Default placement plugin
14451448
if [[ -n "${SOLR_PLACEMENTPLUGIN_DEFAULT:-}" ]] ; then
14461449
SCRIPT_SOLR_OPTS+=("-Dsolr.placementplugin.default=$SOLR_PLACEMENTPLUGIN_DEFAULT")

solr/core/src/java/org/apache/solr/core/CoreContainer.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
import java.util.Set;
5050
import java.util.UUID;
5151
import java.util.concurrent.ConcurrentHashMap;
52+
import java.util.concurrent.Executor;
5253
import java.util.concurrent.ExecutorService;
5354
import java.util.concurrent.TimeoutException;
5455
import java.util.function.Function;
@@ -175,6 +176,10 @@ public class CoreContainer {
175176

176177
final SolrCores solrCores;
177178

179+
public Executor getCollectorExecutor() {
180+
return collectorExecutor;
181+
}
182+
178183
public static class CoreLoadFailure {
179184

180185
public final CoreDescriptor cd;
@@ -278,6 +283,8 @@ public JerseyAppHandlerCache getJerseyAppHandlerCache() {
278283

279284
public final NodeRoles nodeRoles = new NodeRoles(System.getProperty(NodeRoles.NODE_ROLES_PROP));
280285

286+
private final ExecutorService collectorExecutor;
287+
281288
private final ClusterSingletons clusterSingletons =
282289
new ClusterSingletons(
283290
() ->
@@ -432,6 +439,12 @@ public CoreContainer(NodeConfig config, CoresLocator locator, boolean asyncSolrC
432439
this.allowPaths = allowPathBuilder.build();
433440

434441
this.allowListUrlChecker = AllowListUrlChecker.create(config);
442+
443+
this.collectorExecutor =
444+
ExecutorUtil.newMDCAwareCachedThreadPool(
445+
cfg.getIndexSearcherExecutorThreads(), // thread count
446+
cfg.getIndexSearcherExecutorThreads() * 1000, // queue size
447+
new SolrNamedThreadFactory("searcherCollector"));
435448
}
436449

437450
@SuppressWarnings({"unchecked"})
@@ -657,6 +670,7 @@ protected CoreContainer(Object testConstructor) {
657670
distributedCollectionCommandRunner = Optional.empty();
658671
allowPaths = null;
659672
allowListUrlChecker = null;
673+
collectorExecutor = null;
660674
}
661675

662676
public static CoreContainer createAndLoad(Path solrHome) {
@@ -1248,6 +1262,7 @@ public void shutdown() {
12481262
}
12491263

12501264
ExecutorUtil.shutdownAndAwaitTermination(coreContainerAsyncTaskExecutor);
1265+
ExecutorUtil.shutdownAndAwaitTermination(collectorExecutor);
12511266
ExecutorService customThreadPool =
12521267
ExecutorUtil.newMDCAwareCachedThreadPool(new SolrNamedThreadFactory("closeThreadPool"));
12531268

solr/core/src/java/org/apache/solr/core/NodeConfig.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ public class NodeConfig {
105105

106106
private final int replayUpdatesThreads;
107107

108+
private final int indexSearcherExecutorThreads;
109+
108110
@Deprecated private final int transientCacheSize;
109111

110112
private final boolean useSchemaCache;
@@ -144,6 +146,7 @@ private NodeConfig(
144146
CloudConfig cloudConfig,
145147
Integer coreLoadThreads,
146148
int replayUpdatesThreads,
149+
int indexSearcherExecutorThreads,
147150
int transientCacheSize,
148151
boolean useSchemaCache,
149152
String managementPath,
@@ -183,6 +186,7 @@ private NodeConfig(
183186
this.cloudConfig = cloudConfig;
184187
this.coreLoadThreads = coreLoadThreads;
185188
this.replayUpdatesThreads = replayUpdatesThreads;
189+
this.indexSearcherExecutorThreads = indexSearcherExecutorThreads;
186190
this.transientCacheSize = transientCacheSize;
187191
this.useSchemaCache = useSchemaCache;
188192
this.managementPath = managementPath;
@@ -335,6 +339,10 @@ public int getReplayUpdatesThreads() {
335339
return replayUpdatesThreads;
336340
}
337341

342+
public int getIndexSearcherExecutorThreads() {
343+
return indexSearcherExecutorThreads;
344+
}
345+
338346
/**
339347
* Returns a directory, optionally a comma separated list of directories that will be added to
340348
* Solr's class path for searching for classes and plugins. The path is either absolute or
@@ -597,6 +605,7 @@ public static class NodeConfigBuilder {
597605
private CloudConfig cloudConfig;
598606
private int coreLoadThreads = DEFAULT_CORE_LOAD_THREADS;
599607
private int replayUpdatesThreads = Runtime.getRuntime().availableProcessors();
608+
private int indexSearcherExecutorThreads = DEFAULT_INDEX_SEARCHER_EXECUTOR_THREADS;
600609
@Deprecated private int transientCacheSize = -1;
601610
private boolean useSchemaCache = false;
602611
private String managementPath;
@@ -618,6 +627,9 @@ public static class NodeConfigBuilder {
618627
// No:of core load threads in cloud mode is set to a default of 8
619628
public static final int DEFAULT_CORE_LOAD_THREADS_IN_CLOUD = 8;
620629

630+
public static final int DEFAULT_INDEX_SEARCHER_EXECUTOR_THREADS =
631+
4;
632+
621633
private static final String DEFAULT_CORESLOCATORCLASS =
622634
"org.apache.solr.core.CorePropertiesLocator";
623635
private static final String DEFAULT_CORESORTERCLASS = "org.apache.solr.core.CoreSorter";
@@ -755,6 +767,11 @@ public NodeConfigBuilder setReplayUpdatesThreads(int replayUpdatesThreads) {
755767
return this;
756768
}
757769

770+
public NodeConfigBuilder setIndexSearcherExecutorThreads(int indexSearcherExecutorThreads) {
771+
this.indexSearcherExecutorThreads = indexSearcherExecutorThreads;
772+
return this;
773+
}
774+
758775
// Remove in Solr 10.0
759776

760777
@Deprecated
@@ -904,6 +921,7 @@ public NodeConfig build() {
904921
cloudConfig,
905922
coreLoadThreads,
906923
replayUpdatesThreads,
924+
indexSearcherExecutorThreads,
907925
transientCacheSize,
908926
useSchemaCache,
909927
managementPath,

solr/core/src/java/org/apache/solr/core/SolrXmlConfig.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,9 @@ private static NodeConfig fillSolrSection(NodeConfig.NodeConfigBuilder builder,
380380
case "replayUpdatesThreads":
381381
builder.setReplayUpdatesThreads(it.intVal(-1));
382382
break;
383+
case "indexSearcherExecutorThreads":
384+
builder.setIndexSearcherExecutorThreads(it.intVal(-1));
385+
break;
383386
case "transientCacheSize":
384387
log.warn("solr.xml transientCacheSize -- transient cores is deprecated");
385388
builder.setTransientCacheSize(it.intVal(-1));

solr/core/src/java/org/apache/solr/handler/component/QueryComponent.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,10 +372,13 @@ public void process(ResponseBuilder rb) throws IOException {
372372
return;
373373
}
374374

375+
final boolean multiThreaded = params.getBool("multiThreaded", true);
376+
375377
// -1 as flag if not set.
376378
long timeAllowed = params.getLong(CommonParams.TIME_ALLOWED, -1L);
377379

378380
QueryCommand cmd = rb.createQueryCommand();
381+
cmd.setMultiThreaded(multiThreaded);
379382
cmd.setTimeAllowed(timeAllowed);
380383
cmd.setMinExactCount(getMinExactCount(params));
381384
cmd.setDistribStatsDisabled(rb.isDistribStatsDisabled());

0 commit comments

Comments
 (0)