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
return collectorManager.reduce(collectedCollectors);
        }
    }
    @Override
    public void search(List<LeafReaderContext> leaves, Weight weight, Collector collector) throws IOException {
        collector.setWeight(weight);
        for (LeafReaderContext ctx : leaves) { 
            searchLeaf(ctx, weight, collector);
        }
    }
    /**
     * Lower-level search API.
     *
     * {@link LeafCollector#collect(int)} is called for every matching document in
     * the provided <code>ctx</code>.
     */
    private void searchLeaf(LeafReaderContext ctx, Weight weight, Collector collector) throws IOException {
        cancellable.checkCancelled();
        final LeafCollector leafCollector;
        try {
            leafCollector = collector.getLeafCollector(ctx);
        } catch (CollectionTerminatedException e) {
            
            
            return;
        }
        Bits liveDocs = ctx.reader().getLiveDocs();
        BitSet liveDocsBitSet = getSparseBitSetOrNull(liveDocs);
        if (liveDocsBitSet == null) {
            BulkScorer bulkScorer = weight.bulkScorer(ctx);