Skip to content

Commit 4410b34

Browse files
Added debug logging, measure execution times of 2nd search.
Signed-off-by: Dooyong Kim <[email protected]>
1 parent 0999890 commit 4410b34

16 files changed

+138
-847
lines changed

src/main/java/org/opensearch/knn/index/query/KNNWeight.java

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import org.apache.lucene.util.BitSetIterator;
2525
import org.apache.lucene.util.Bits;
2626
import org.apache.lucene.util.FixedBitSet;
27-
import org.opensearch.common.Nullable;
2827
import org.opensearch.common.StopWatch;
2928
import org.opensearch.common.lucene.Lucene;
3029
import org.opensearch.knn.common.FieldInfoExtractor;
@@ -52,6 +51,9 @@
5251
import static org.opensearch.knn.common.KNNConstants.SPACE_TYPE;
5352
import static org.opensearch.knn.common.KNNConstants.VECTOR_DATA_TYPE_FIELD;
5453

54+
import static org.opensearch.knn.profile.StopWatchUtils.startStopWatch;
55+
import static org.opensearch.knn.profile.StopWatchUtils.stopStopWatchAndLog;
56+
5557
/**
5658
* {@link KNNWeight} serves as a template for implementing approximate nearest neighbor (ANN)
5759
* and radius search over a native index type, such as Faiss.
@@ -298,9 +300,9 @@ public PerLeafResult searchLeaf(LeafReaderContext context, int k) throws IOExcep
298300
final SegmentReader reader = Lucene.segmentReader(context.reader());
299301
final String segmentName = reader.getSegmentName();
300302

301-
StopWatch stopWatch = startStopWatch();
303+
final StopWatch stopWatch = startStopWatch(log);
302304
final BitSet filterBitSet = getFilteredDocsBitSet(context);
303-
stopStopWatchAndLog(stopWatch, "FilterBitSet creation", segmentName);
305+
stopStopWatchAndLog(log, stopWatch, "FilterBitSet creation", knnQuery.getShardId(), segmentName, knnQuery.getField());
304306

305307
// Save its cardinality, as the cardinality calculation is expensive.
306308
final int filterCardinality = filterBitSet.cardinality();
@@ -330,9 +332,10 @@ public PerLeafResult searchLeaf(LeafReaderContext context, int k) throws IOExcep
330332
);
331333
}
332334

333-
StopWatch annStopWatch = startStopWatch();
335+
final StopWatch annStopWatch = startStopWatch(log);
334336
final TopDocs topDocs = approximateSearch(context, filterBitSet, filterCardinality, k);
335-
stopStopWatchAndLog(annStopWatch, "ANN search", segmentName);
337+
stopStopWatchAndLog(log, stopWatch, "ANN search", knnQuery.getShardId(), segmentName, knnQuery.getField());
338+
336339
if (knnQuery.isExplain()) {
337340
knnExplanation.addLeafResult(context.id(), topDocs.scoreDocs.length);
338341
}
@@ -358,14 +361,6 @@ public PerLeafResult searchLeaf(LeafReaderContext context, int k) throws IOExcep
358361
);
359362
}
360363

361-
private void stopStopWatchAndLog(@Nullable final StopWatch stopWatch, final String prefixMessage, String segmentName) {
362-
if (log.isDebugEnabled() && stopWatch != null) {
363-
stopWatch.stop();
364-
final String logMessage = prefixMessage + " shard: [{}], segment: [{}], field: [{}], time in nanos:[{}] ";
365-
log.debug(logMessage, knnQuery.getShardId(), segmentName, knnQuery.getField(), stopWatch.totalTime().nanos());
366-
}
367-
}
368-
369364
protected BitSet getFilteredDocsBitSet(final LeafReaderContext ctx) throws IOException {
370365
if (this.filterWeight == null) {
371366
return new FixedBitSet(0);
@@ -593,10 +588,10 @@ protected void addExplainIfRequired(final TopDocs results, final KNNEngine knnEn
593588
*/
594589
public TopDocs exactSearch(final LeafReaderContext leafReaderContext, final ExactSearcher.ExactSearcherContext exactSearcherContext)
595590
throws IOException {
596-
StopWatch stopWatch = startStopWatch();
591+
final StopWatch stopWatch = startStopWatch(log);
597592
TopDocs exactSearchResults = exactSearcher.searchLeaf(leafReaderContext, exactSearcherContext);
598593
final SegmentReader reader = Lucene.segmentReader(leafReaderContext.reader());
599-
stopStopWatchAndLog(stopWatch, "Exact search", reader.getSegmentName());
594+
stopStopWatchAndLog(log, stopWatch, "Exact search", knnQuery.getShardId(), reader.getSegmentName(), knnQuery.getField());
600595
return exactSearchResults;
601596
}
602597

@@ -713,13 +708,6 @@ private boolean isMissingNativeEngineFiles(LeafReaderContext context) {
713708
return engineFiles.isEmpty();
714709
}
715710

716-
private StopWatch startStopWatch() {
717-
if (log.isDebugEnabled()) {
718-
return new StopWatch().start();
719-
}
720-
return null;
721-
}
722-
723711
protected int[] getParentIdsArray(final LeafReaderContext context) throws IOException {
724712
if (knnQuery.getParentsFilter() == null) {
725713
return null;

src/main/java/org/opensearch/knn/index/query/memoryoptsearch/MemoryOptimizedKNNWeight.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.opensearch.knn.index.query.KNNWeight;
3232
import org.opensearch.knn.index.query.MemoryOptimizedSearchScoreConverter;
3333
import org.opensearch.lucene.OptimisticKnnCollectorManager;
34+
import org.opensearch.lucene.ReentrantKnnCollectorManager;
3435

3536
import java.io.IOException;
3637

@@ -50,7 +51,7 @@ public class MemoryOptimizedKNNWeight extends KNNWeight {
5051

5152
private final KnnCollectorManager knnCollectorManager;
5253
@Setter
53-
private KnnCollectorManager optimistic2ndKnnCollectorManager;
54+
private ReentrantKnnCollectorManager reentrantKNNCollectorManager;
5455

5556
public MemoryOptimizedKNNWeight(KNNQuery query, float boost, final Weight filterWeight, IndexSearcher searcher, Integer k) {
5657
super(query, boost, filterWeight);
@@ -188,8 +189,8 @@ private TopDocs queryIndex(
188189
}
189190

190191
// Create a collector + bitset
191-
final KnnCollectorManager collectorManager = optimistic2ndKnnCollectorManager != null
192-
? optimistic2ndKnnCollectorManager
192+
final KnnCollectorManager collectorManager = reentrantKNNCollectorManager != null
193+
? reentrantKNNCollectorManager
193194
: knnCollectorManager;
194195
final KnnCollector knnCollector = collectorManager.newCollector(visitedLimit, DEFAULT_HNSW_SEARCH_STRATEGY, context);
195196
final AcceptDocs acceptDocs = getAcceptedDocs(reader, cardinality, filterIdsBitSet);

src/main/java/org/opensearch/knn/index/query/nativelib/NativeEngineKnnVectorQuery.java

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@
5353
import java.util.concurrent.Callable;
5454
import java.util.stream.Collectors;
5555

56+
import static org.opensearch.knn.profile.StopWatchUtils.startStopWatch;
57+
import static org.opensearch.knn.profile.StopWatchUtils.stopStopWatchAndLog;
58+
5659
/**
5760
* {@link KNNQuery} executes approximate nearest neighbor search (ANN) on a segment level.
5861
* {@link NativeEngineKnnVectorQuery} executes approximate nearest neighbor search but gives
@@ -274,13 +277,19 @@ private List<PerLeafResult> doSearch(
274277

275278
// For memory optimized search, it should kick off 2nd search if optimistic
276279
if (knnQuery.isMemoryOptimizedSearch() && perLeafResults.size() > 1) {
277-
run2ndOptimisticSearch(perLeafResults, knnWeight, leafReaderContexts, k, indexSearcher);
280+
log.debug(
281+
"Running second deep dive search in optimistic while memory optimized search is enabled. perLeafResults.size()={}",
282+
perLeafResults.size()
283+
);
284+
final StopWatch stopWatch = startStopWatch(log);
285+
reentrantSearch(perLeafResults, knnWeight, leafReaderContexts, k, indexSearcher);
286+
stopStopWatchAndLog(log, stopWatch, "2ndOptimisticSearch", knnQuery.getShardId(), "All Shards", knnQuery.getField());
278287
}
279288

280289
return perLeafResults;
281290
}
282291

283-
private void run2ndOptimisticSearch(
292+
private void reentrantSearch(
284293
final List<PerLeafResult> perLeafResults,
285294
final KNNWeight knnWeight,
286295
final List<LeafReaderContext> leafReaderContexts,
@@ -299,7 +308,7 @@ private void run2ndOptimisticSearch(
299308

300309
assert (perLeafResults.size() == leafReaderContexts.size());
301310

302-
// Get collector manager first
311+
// Get memory optimized knn weight first, it's safe get it, we checked it already.
303312
final MemoryOptimizedKNNWeight memoryOptKNNWeight = (MemoryOptimizedKNNWeight) knnWeight;
304313

305314
// How many results have we collected?
@@ -313,25 +322,24 @@ private void run2ndOptimisticSearch(
313322
return;
314323
}
315324

316-
// Build segment to results table
317-
final Map<Integer, TopDocs> segmentOrdToResults = new HashMap<>(leafReaderContexts.size());
318-
for (int i = 0; i < perLeafResults.size(); i++) {
319-
segmentOrdToResults.put(leafReaderContexts.get(i).ord, perLeafResults.get(i).getResult());
320-
}
321-
322325
// Start 2nd deep dive, and get the minimum bar.
323326
final float minTopKScore = OptimisticSearchStrategyUtils.findKthLargestScore(perLeafResults, knnQuery.getK(), totalResults);
324327

325328
// Select candidate segments for 2nd search. Pick whatever segment returned all vectors whose score values are greater than `kth`
326329
// value in the merged results.
327330
final List<Callable<TopDocs>> secondDeepDiveTasks = new ArrayList<>();
328331
final List<Integer> contextIndices = new ArrayList<>();
332+
final Map<Integer, TopDocs> segmentOrdToResults = new HashMap<>();
333+
329334
for (int i = 0; i < leafReaderContexts.size(); ++i) {
330335
final LeafReaderContext leafReaderContext = leafReaderContexts.get(i);
331336
final PerLeafResult perLeafResult = perLeafResults.get(i);
332-
final TopDocs perLeaf = segmentOrdToResults.get(leafReaderContext.ord);
337+
final TopDocs perLeaf = perLeafResults.get(i).getResult();
333338
if (perLeaf.scoreDocs.length > 0 && perLeafResult.getSearchMode() == PerLeafResult.SearchMode.APPROXIMATE_SEARCH) {
334339
if (FORCE_REENTER_TESTING || perLeaf.scoreDocs[perLeaf.scoreDocs.length - 1].score >= minTopKScore) {
340+
// For the target segment, save top results. Which will be used as seeds.
341+
segmentOrdToResults.put(leafReaderContext.ord, perLeaf);
342+
335343
// All this leaf's hits are at or above the global topK min score; explore it further
336344
secondDeepDiveTasks.add(
337345
() -> knnWeight.approximateSearch(
@@ -348,24 +356,24 @@ private void run2ndOptimisticSearch(
348356

349357
// Kick off 2nd search tasks
350358
if (secondDeepDiveTasks.isEmpty() == false) {
351-
final ReentrantKnnCollectorManager knnCollectorManagerPhase2 = new ReentrantKnnCollectorManager(
359+
final ReentrantKnnCollectorManager reentrantCollectorManager = new ReentrantKnnCollectorManager(
352360
new TopKnnCollectorManager(k, indexSearcher),
353361
segmentOrdToResults,
354362
knnQuery.getQueryVector(),
355363
knnQuery.getField()
356364
);
357365

358366
// Make weight use reentrant collector manager
359-
memoryOptKNNWeight.setOptimistic2ndKnnCollectorManager(knnCollectorManagerPhase2);
367+
memoryOptKNNWeight.setReentrantKNNCollectorManager(reentrantCollectorManager);
360368

361369
final List<TopDocs> deepDiveTopDocs = indexSearcher.getTaskExecutor().invokeAll(secondDeepDiveTasks);
362370

363371
// Override results for target context
364372
for (int i = 0; i < deepDiveTopDocs.size(); ++i) {
365373
// Override with the new results
366-
final TopDocs resultsFrom2ncDeepDive = deepDiveTopDocs.get(i);
374+
final TopDocs resultsFromDeepDive = deepDiveTopDocs.get(i);
367375
final PerLeafResult perLeafResult = perLeafResults.get(contextIndices.get(i));
368-
perLeafResult.setResult(resultsFrom2ncDeepDive);
376+
perLeafResult.setResult(resultsFromDeepDive);
369377
}
370378
}
371379
}

src/main/java/org/opensearch/knn/memoryoptsearch/MemorySegmentAddressExtractor.java

Lines changed: 0 additions & 24 deletions
This file was deleted.

src/main/java/org/opensearch/knn/memoryoptsearch/MemorySegmentAddressExtractorJDK21.java

Lines changed: 0 additions & 97 deletions
This file was deleted.

0 commit comments

Comments
 (0)