Skip to content

Commit bc88c29

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 135f7eb commit bc88c29

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;
@@ -128,7 +130,13 @@ public Scorer scorer(LeafReaderContext context) throws IOException {
128130
* @return A Map of docId to scores for top k results
129131
*/
130132
public PerLeafResult searchLeaf(LeafReaderContext context, int k) throws IOException {
133+
final SegmentReader reader = Lucene.segmentReader(context.reader());
134+
final String segmentName = reader.getSegmentName();
135+
136+
StopWatch stopWatch = startStopWatch();
131137
final BitSet filterBitSet = getFilteredDocsBitSet(context);
138+
stopStopWatchAndLog(stopWatch, "FilterBitSet creation", segmentName);
139+
132140
final int maxDoc = context.reader().maxDoc();
133141
int cardinality = filterBitSet.cardinality();
134142
// We don't need to go to JNI layer if no documents are found which satisfy the filters
@@ -152,7 +160,10 @@ public PerLeafResult searchLeaf(LeafReaderContext context, int k) throws IOExcep
152160
* so that it will not do a bitset look up in bottom search layer.
153161
*/
154162
final BitSet annFilter = (filterWeight != null && cardinality == maxDoc) ? null : filterBitSet;
155-
final Map<Integer, Float> docIdsToScoreMap = doANNSearch(context, annFilter, cardinality, k);
163+
164+
StopWatch annStopWatch = startStopWatch();
165+
final Map<Integer, Float> docIdsToScoreMap = doANNSearch(reader, context, annFilter, cardinality, k);
166+
stopStopWatchAndLog(annStopWatch, "ANN search", segmentName);
156167

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

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

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

248266
if (fieldInfo == null) {
@@ -401,7 +419,11 @@ public Map<Integer, Float> exactSearch(
401419
final LeafReaderContext leafReaderContext,
402420
final ExactSearcher.ExactSearcherContext exactSearcherContext
403421
) throws IOException {
404-
return exactSearcher.searchLeaf(leafReaderContext, exactSearcherContext);
422+
StopWatch stopWatch = startStopWatch();
423+
Map<Integer, Float> exactSearchResults = exactSearcher.searchLeaf(leafReaderContext, exactSearcherContext);
424+
final SegmentReader reader = Lucene.segmentReader(leafReaderContext.reader());
425+
stopStopWatchAndLog(stopWatch, "Exact search", reader.getSegmentName());
426+
return exactSearchResults;
405427
}
406428

407429
@Override
@@ -508,4 +530,11 @@ private boolean isMissingNativeEngineFiles(LeafReaderContext context) {
508530
);
509531
return engineFiles.isEmpty();
510532
}
533+
534+
private StopWatch startStopWatch() {
535+
if (log.isDebugEnabled()) {
536+
return new StopWatch().start();
537+
}
538+
return null;
539+
}
511540
}

0 commit comments

Comments
 (0)