diff --git a/lucene/core/src/java/org/apache/lucene/index/CachingMergeContext.java b/lucene/core/src/java/org/apache/lucene/index/CachingMergeContext.java new file mode 100644 index 000000000000..9661ab91e76a --- /dev/null +++ b/lucene/core/src/java/org/apache/lucene/index/CachingMergeContext.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.lucene.index; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Set; +import org.apache.lucene.util.InfoStream; + +/** + * a wrapper of IndexWriter MergeContext. Try to cache the {@link + * #numDeletesToMerge(SegmentCommitInfo)} result in merge phase, to avoid duplicate calculation + */ +public class CachingMergeContext implements MergePolicy.MergeContext { + final MergePolicy.MergeContext mergeContext; + final HashMap cachedNumDeletesToMerge = new HashMap<>(); + + CachingMergeContext(MergePolicy.MergeContext mergeContext) { + this.mergeContext = mergeContext; + } + + @Override + public final int numDeletesToMerge(SegmentCommitInfo info) throws IOException { + Integer numDeletesToMerge = cachedNumDeletesToMerge.get(info); + if (numDeletesToMerge != null) { + return numDeletesToMerge; + } + numDeletesToMerge = mergeContext.numDeletesToMerge(info); + cachedNumDeletesToMerge.put(info, numDeletesToMerge); + return numDeletesToMerge; + } + + @Override + public final int numDeletedDocs(SegmentCommitInfo info) { + return mergeContext.numDeletedDocs(info); + } + + @Override + public final InfoStream getInfoStream() { + return mergeContext.getInfoStream(); + } + + @Override + public final Set getMergingSegments() { + return mergeContext.getMergingSegments(); + } +} diff --git a/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java b/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java index 33cec219fac2..b562f7740d29 100644 --- a/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java +++ b/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java @@ -2214,10 +2214,11 @@ public void forceMergeDeletes(boolean doWait) throws IOException { } final MergePolicy mergePolicy = config.getMergePolicy(); + final CachingMergeContext cachingMergeContext = new CachingMergeContext(this); MergePolicy.MergeSpecification spec; boolean newMergesFound = false; synchronized (this) { - spec = mergePolicy.findForcedDeletesMerges(segmentInfos, this); + spec = mergePolicy.findForcedDeletesMerges(segmentInfos, cachingMergeContext); newMergesFound = spec != null; if (newMergesFound) { final int numMerges = spec.merges.size(); @@ -2327,6 +2328,7 @@ private synchronized MergePolicy.MergeSpecification updatePendingMerges( } final MergePolicy.MergeSpecification spec; + final CachingMergeContext cachingMergeContext = new CachingMergeContext(this); if (maxNumSegments != UNBOUNDED_MAX_MERGE_SEGMENTS) { assert trigger == MergeTrigger.EXPLICIT || trigger == MergeTrigger.MERGE_FINISHED : "Expected EXPLICT or MERGE_FINISHED as trigger even with maxNumSegments set but was: " @@ -2334,7 +2336,10 @@ private synchronized MergePolicy.MergeSpecification updatePendingMerges( spec = mergePolicy.findForcedMerges( - segmentInfos, maxNumSegments, Collections.unmodifiableMap(segmentsToMerge), this); + segmentInfos, + maxNumSegments, + Collections.unmodifiableMap(segmentsToMerge), + cachingMergeContext); if (spec != null) { final int numMerges = spec.merges.size(); for (int i = 0; i < numMerges; i++) { @@ -2346,7 +2351,7 @@ private synchronized MergePolicy.MergeSpecification updatePendingMerges( switch (trigger) { case GET_READER: case COMMIT: - spec = mergePolicy.findFullFlushMerges(trigger, segmentInfos, this); + spec = mergePolicy.findFullFlushMerges(trigger, segmentInfos, cachingMergeContext); break; case ADD_INDEXES: throw new IllegalStateException( @@ -2358,7 +2363,7 @@ private synchronized MergePolicy.MergeSpecification updatePendingMerges( case SEGMENT_FLUSH: case CLOSING: default: - spec = mergePolicy.findMerges(trigger, segmentInfos, this); + spec = mergePolicy.findMerges(trigger, segmentInfos, cachingMergeContext); } } if (spec != null) {