Skip to content

Commit cc38cc0

Browse files
shatejasgithub-actions[bot]
authored andcommitted
Adds debug logs for KNNQuery and KNNWeight (#2466)
* Adds debug logs for KNNQuery and KNNWeight Signed-off-by: Tejas Shah <[email protected]> * Adds check to see if log is enabled to start and stop StopWatch Signed-off-by: Tejas Shah <[email protected]> * Addressing comments on the PR Signed-off-by: Tejas Shah <[email protected]> * Adds shard and segment info in the logs Signed-off-by: Tejas Shah <[email protected]> * Removes unnecessary segment name param from exact search Signed-off-by: Tejas Shah <[email protected]> * Fixes the build Signed-off-by: Tejas Shah <[email protected]> --------- Signed-off-by: Tejas Shah <[email protected]> (cherry picked from commit f322e27)
1 parent 9b07a12 commit cc38cc0

File tree

3 files changed

+60
-6
lines changed

3 files changed

+60
-6
lines changed

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

+22-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import lombok.EqualsAndHashCode;
1111
import lombok.Getter;
1212
import lombok.Setter;
13+
import lombok.extern.log4j.Log4j2;
1314
import org.apache.lucene.search.BooleanClause;
1415
import org.apache.lucene.search.BooleanQuery;
1516
import org.apache.lucene.search.FieldExistsQuery;
@@ -19,6 +20,7 @@
1920
import org.apache.lucene.search.ScoreMode;
2021
import org.apache.lucene.search.Weight;
2122
import org.apache.lucene.search.join.BitSetProducer;
23+
import org.opensearch.common.StopWatch;
2224
import org.opensearch.knn.index.KNNSettings;
2325
import org.opensearch.knn.index.VectorDataType;
2426
import org.opensearch.knn.index.query.rescore.RescoreContext;
@@ -32,6 +34,7 @@
3234
* Custom KNN query. Query is used for KNNEngine's that create their own custom segment files. These files need to be
3335
* loaded and queried in a custom manner throughout the query path.
3436
*/
37+
@Log4j2
3538
@Getter
3639
@Builder
3740
@AllArgsConstructor
@@ -45,14 +48,17 @@ public class KNNQuery extends Query {
4548
private final String indexName;
4649
private final VectorDataType vectorDataType;
4750
private final RescoreContext rescoreContext;
48-
4951
@Setter
5052
private Query filterQuery;
5153
@Getter
5254
private BitSetProducer parentsFilter;
5355
private Float radius;
5456
private Context context;
5557

58+
// Note: ideally query should not have to deal with shard level information. Adding it for logging purposes only
59+
// TODO: ThreadContext does not work with logger, remove this from here once its figured out
60+
private int shardId;
61+
5662
public KNNQuery(
5763
final String field,
5864
final float[] queryVector,
@@ -168,7 +174,22 @@ public Weight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float bo
168174
if (!KNNSettings.isKNNPluginEnabled()) {
169175
throw new IllegalStateException("KNN plugin is disabled. To enable update knn.plugin.enabled to true");
170176
}
177+
StopWatch stopWatch = null;
178+
if (log.isDebugEnabled()) {
179+
stopWatch = new StopWatch().start();
180+
}
181+
171182
final Weight filterWeight = getFilterWeight(searcher);
183+
if (log.isDebugEnabled() && stopWatch != null) {
184+
stopWatch.stop();
185+
log.debug(
186+
"Creating filter weight, Shard: [{}], field: [{}] took in nanos: [{}]",
187+
shardId,
188+
field,
189+
stopWatch.totalTime().nanos()
190+
);
191+
}
192+
172193
if (filterWeight != null) {
173194
return new KNNWeight(this, boost, filterWeight);
174195
}

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

+4
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,11 @@ public static Query create(CreateQueryRequest createQueryRequest) {
5252
final KNNEngine knnEngine = createQueryRequest.getKnnEngine();
5353
final boolean expandNested = createQueryRequest.getExpandNested().orElse(false);
5454
BitSetProducer parentFilter = null;
55+
int shardId = -1;
5556
if (createQueryRequest.getContext().isPresent()) {
5657
QueryShardContext context = createQueryRequest.getContext().get();
5758
parentFilter = context.getParentFilter();
59+
shardId = context.getShardId();
5860
}
5961

6062
if (parentFilter == null && expandNested) {
@@ -93,6 +95,7 @@ public static Query create(CreateQueryRequest createQueryRequest) {
9395
.filterQuery(validatedFilterQuery)
9496
.vectorDataType(vectorDataType)
9597
.rescoreContext(rescoreContext)
98+
.shardId(shardId)
9699
.build();
97100
break;
98101
default:
@@ -106,6 +109,7 @@ public static Query create(CreateQueryRequest createQueryRequest) {
106109
.filterQuery(validatedFilterQuery)
107110
.vectorDataType(vectorDataType)
108111
.rescoreContext(rescoreContext)
112+
.shardId(shardId)
109113
.build();
110114
}
111115

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

+34-5
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
import org.apache.lucene.util.BitSetIterator;
2121
import org.apache.lucene.util.Bits;
2222
import org.apache.lucene.util.FixedBitSet;
23+
import org.opensearch.common.Nullable;
24+
import org.opensearch.common.StopWatch;
2325
import org.opensearch.common.lucene.Lucene;
2426
import org.opensearch.knn.common.FieldInfoExtractor;
2527
import org.opensearch.knn.common.KNNConstants;
@@ -129,7 +131,13 @@ public Scorer scorer(LeafReaderContext context) throws IOException {
129131
* @return A Map of docId to scores for top k results
130132
*/
131133
public PerLeafResult searchLeaf(LeafReaderContext context, int k) throws IOException {
134+
final SegmentReader reader = Lucene.segmentReader(context.reader());
135+
final String segmentName = reader.getSegmentName();
136+
137+
StopWatch stopWatch = startStopWatch();
132138
final BitSet filterBitSet = getFilteredDocsBitSet(context);
139+
stopStopWatchAndLog(stopWatch, "FilterBitSet creation", segmentName);
140+
133141
final int maxDoc = context.reader().maxDoc();
134142
int cardinality = filterBitSet.cardinality();
135143
// We don't need to go to JNI layer if no documents are found which satisfy the filters
@@ -153,7 +161,10 @@ public PerLeafResult searchLeaf(LeafReaderContext context, int k) throws IOExcep
153161
* so that it will not do a bitset look up in bottom search layer.
154162
*/
155163
final BitSet annFilter = (filterWeight != null && cardinality == maxDoc) ? null : filterBitSet;
156-
final Map<Integer, Float> docIdsToScoreMap = doANNSearch(context, annFilter, cardinality, k);
164+
165+
StopWatch annStopWatch = startStopWatch();
166+
final Map<Integer, Float> docIdsToScoreMap = doANNSearch(reader, context, annFilter, cardinality, k);
167+
stopStopWatchAndLog(annStopWatch, "ANN search", segmentName);
157168

158169
// See whether we have to perform exact search based on approx search results
159170
// This is required if there are no native engine files or if approximate search returned
@@ -166,6 +177,14 @@ public PerLeafResult searchLeaf(LeafReaderContext context, int k) throws IOExcep
166177
return new PerLeafResult(filterWeight == null ? null : filterBitSet, docIdsToScoreMap);
167178
}
168179

180+
private void stopStopWatchAndLog(@Nullable final StopWatch stopWatch, final String prefixMessage, String segmentName) {
181+
if (log.isDebugEnabled() && stopWatch != null) {
182+
stopWatch.stop();
183+
final String logMessage = prefixMessage + " shard: [{}], segment: [{}], field: [{}], time in nanos:[{}] ";
184+
log.debug(logMessage, knnQuery.getShardId(), segmentName, knnQuery.getField(), stopWatch.totalTime().nanos());
185+
}
186+
}
187+
169188
private BitSet getFilteredDocsBitSet(final LeafReaderContext ctx) throws IOException {
170189
if (this.filterWeight == null) {
171190
return new FixedBitSet(0);
@@ -222,7 +241,7 @@ private Map<Integer, Float> doExactSearch(
222241
final LeafReaderContext context,
223242
final DocIdSetIterator acceptedDocs,
224243
final long numberOfAcceptedDocs,
225-
int k
244+
final int k
226245
) throws IOException {
227246
final ExactSearcherContextBuilder exactSearcherContextBuilder = ExactSearcher.ExactSearcherContext.builder()
228247
.isParentHits(true)
@@ -237,13 +256,12 @@ private Map<Integer, Float> doExactSearch(
237256
}
238257

239258
private Map<Integer, Float> doANNSearch(
259+
final SegmentReader reader,
240260
final LeafReaderContext context,
241261
final BitSet filterIdsBitSet,
242262
final int cardinality,
243263
final int k
244264
) throws IOException {
245-
final SegmentReader reader = Lucene.segmentReader(context.reader());
246-
247265
FieldInfo fieldInfo = FieldInfoExtractor.getFieldInfo(reader, knnQuery.getField());
248266

249267
if (fieldInfo == null) {
@@ -402,7 +420,11 @@ public Map<Integer, Float> exactSearch(
402420
final LeafReaderContext leafReaderContext,
403421
final ExactSearcher.ExactSearcherContext exactSearcherContext
404422
) throws IOException {
405-
return exactSearcher.searchLeaf(leafReaderContext, exactSearcherContext);
423+
StopWatch stopWatch = startStopWatch();
424+
Map<Integer, Float> exactSearchResults = exactSearcher.searchLeaf(leafReaderContext, exactSearcherContext);
425+
final SegmentReader reader = Lucene.segmentReader(leafReaderContext.reader());
426+
stopStopWatchAndLog(stopWatch, "Exact search", reader.getSegmentName());
427+
return exactSearchResults;
406428
}
407429

408430
@Override
@@ -523,4 +545,11 @@ private boolean isMissingNativeEngineFiles(LeafReaderContext context) {
523545
);
524546
return engineFiles.isEmpty();
525547
}
548+
549+
private StopWatch startStopWatch() {
550+
if (log.isDebugEnabled()) {
551+
return new StopWatch().start();
552+
}
553+
return null;
554+
}
526555
}

0 commit comments

Comments
 (0)