In order to implement multi threaded search we need to adjust the logic that creates the slices.
The new slice logic should take the following into account:

- A minimum doc count per slice. In order to avoid a number of aggregations to produce in-accurate results, a slice should at least contain 10% of the total documents in the Lucene index.
- A maximum number of slices. The number of slices that a shard level search creates should be capped. To avoid creating more slices than available search threads.
server/src/main/java/org/elasticsearch/search/internal/ContextIndexSearcher.java
/**
     * The interval at which we check for search cancellation when we cannot use
     * a {@link CancellableBulkScorer}. See {@link #intersectScorerAndBitSet}.
     */
    private static final int CHECK_CANCELLED_SCORER_INTERVAL = 1 << 11;
    private AggregatedDfs aggregatedDfs;
    private QueryProfiler profiler;
    private final MutableQueryTimeout cancellable;
    private final QueueSizeBasedExecutor queueSizeBasedExecutor;
    private final LeafSlice[] leafSlices;
    
    public ContextIndexSearcher(
        IndexReader reader,
        Similarity similarity,
        QueryCache queryCache,
        QueryCachingPolicy queryCachingPolicy,
        boolean wrapWithExitableDirectoryReader
    ) throws IOException {
        this(reader, similarity, queryCache, queryCachingPolicy, new MutableQueryTimeout(), wrapWithExitableDirectoryReader, null);
    }
    
    public ContextIndexSearcher(
        IndexReader reader,
        Similarity similarity,
        QueryCache queryCache,
        QueryCachingPolicy queryCachingPolicy,
        boolean wrapWithExitableDirectoryReader,
        ThreadPoolExecutor executor
    ) throws IOException {
        this(reader, similarity, queryCache, queryCachingPolicy, new MutableQueryTimeout(), wrapWithExitableDirectoryReader, executor);