SOLR-17841: Use DocSetCollector for multithreaded DocSet(Faceted) search - #4724
SOLR-17841: Use DocSetCollector for multithreaded DocSet(Faceted) search#4724punAhuja wants to merge 3 commits into
Conversation
Co-authored-by: David Smiley <dsmiley@apache.org>
Co-authored-by: David Smiley <dsmiley@apache.org>
|
Thanks for this! Did you consider & reject use of the |
Multithreaded search parralelizes searching on different segments. So more segments = more parallelization. I was testing on a dataset with 1M docs, so I configured it to use NoMerge policy and flush at every 2k docs so I have more segments in the index. I didn't consider solr/benchmark as I have used solr-bench and am comfortable with it. |
| } | ||
|
|
||
| static boolean allowMT(DelegatingCollector postFilter, QueryCommand cmd) { | ||
| static boolean allowMT(DelegatingCollector postFilter, QueryCommand cmd, boolean hasExecutor) { |
There was a problem hiding this comment.
I find this method rather inelegant. It takes several args, one of which is a boolean (problematic to discern meaning at call-site in Java; no named-args). The method's only purpose is to decide yes/no on something. Notice that this method takes a postFilter and we do a null check. I think it'd be slightly improved to replace this boolean you added with the executor itself.
| } | ||
|
|
||
| static boolean allowMT(DelegatingCollector postFilter, QueryCommand cmd) { | ||
| static boolean allowMT(DelegatingCollector postFilter, QueryCommand cmd, boolean hasExecutor) { |
There was a problem hiding this comment.
I find this method rather inelegant. It takes several args, one of which is a boolean (problematic to discern meaning at call-site in Java; no named-args). The method's only purpose is to decide yes/no on something. Notice that this method takes a postFilter and we do a null check. I think it'd be slightly improved to replace this boolean you added with the executor itself.
https://issues.apache.org/jira/browse/SOLR-17841
Description
Multithreaded(MT) search was slower than Singlethreaded(ST) search in the case of faceted queries. Faceted queries need a DocSet. ST already builds that with
DocSetCollector. MT used a customFixedBitSetCollectorinstead, and that made faceted search slower with MT on.This PR fixes that DocSet path so enabling MT no longer makes faceting worse.
Solution
Two changes in
MultiThreadedSearcher/SolrIndexSearcher:DocSetCollector, same as the single-threaded path. Each thread collects its own DocSet, then we OR them together. The oldFixedBitSetCollectorwas only used here, so I removed it.multiThreaded=truenow also needs a searcher thread pool. IfindexSearcherExecutorThreads=0, we used to take the multithreaded path anyway and it could get very slow. That case now falls back to single-threaded.I used an AI coding assistant (Cursor) while investigating and drafting the change. I reviewed the diff, ran the tests, and did the benchmarks myself.
Tests
Unit test:
TestMultiThreadedSearcher.testMultiThreadedDocSetMatchesSingleThreaded— same query,needDocSet=true, ST vs MT DocSets must match on a multi-segment index.Latency was measured with solr-bench (one client query at a time; searcher
pool
-Dsolr.searchThreads=-1). Suites, generator, NoMerge configset, andhow to run it:
https://github.com/SearchScale/solr-bench/tree/puneet/SOLR-17841-mt-search
I compared the same 1M-doc index merged vs forced to ~500 segments
(
NoMergePolicy, flush every 2000 docs). Queries areevent_timerange +event_typefilter, with and without facets.After the fix, facet MT is no longer worse on a normal index. With many
segments MT can win, especially on plain queries and p95.
NOTE: Still investigating whether MT can actually beat ST more broadly.
This PR only addresses the DocSet collector used for faceting. After the change, facet MT is no longer worse on a normal index, and with many segments MT can win (especially plain queries and p95).
Renato's findings on SOLR-17841 look like a separate bottleneck. Even with 50M docs force-merged to 5 segments, range queries were ~5× slower under MT; the profile pointed at
SolrRangeQuery/FixedBitSet.or, not this collector. I want to look at that next.Checklist
Please review the following and check all that apply:
mainbranch../gradlew check.