Skip to content

Commit 82e314e

Browse files
Adds debug logs for KNNQuery and KNNWeight (#2466) (#2470)
* 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) Co-authored-by: Tejas Shah <[email protected]>
1 parent b770281 commit 82e314e

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
@@ -21,6 +21,8 @@
2121
import org.apache.lucene.util.BitSetIterator;
2222
import org.apache.lucene.util.Bits;
2323
import org.apache.lucene.util.FixedBitSet;
24+
import org.opensearch.common.Nullable;
25+
import org.opensearch.common.StopWatch;
2426
import org.opensearch.common.lucene.Lucene;
2527
import org.opensearch.knn.common.FieldInfoExtractor;
2628
import org.opensearch.knn.common.KNNConstants;
@@ -143,7 +145,13 @@ public long cost() {
143145
* @return A Map of docId to scores for top k results
144146
*/
145147
public PerLeafResult searchLeaf(LeafReaderContext context, int k) throws IOException {
148+
final SegmentReader reader = Lucene.segmentReader(context.reader());
149+
final String segmentName = reader.getSegmentName();
150+
151+
StopWatch stopWatch = startStopWatch();
146152
final BitSet filterBitSet = getFilteredDocsBitSet(context);
153+
stopStopWatchAndLog(stopWatch, "FilterBitSet creation", segmentName);
154+
147155
final int maxDoc = context.reader().maxDoc();
148156
int cardinality = filterBitSet.cardinality();
149157
// We don't need to go to JNI layer if no documents are found which satisfy the filters
@@ -167,7 +175,10 @@ public PerLeafResult searchLeaf(LeafReaderContext context, int k) throws IOExcep
167175
* so that it will not do a bitset look up in bottom search layer.
168176
*/
169177
final BitSet annFilter = (filterWeight != null && cardinality == maxDoc) ? null : filterBitSet;
170-
final Map<Integer, Float> docIdsToScoreMap = doANNSearch(context, annFilter, cardinality, k);
178+
179+
StopWatch annStopWatch = startStopWatch();
180+
final Map<Integer, Float> docIdsToScoreMap = doANNSearch(reader, context, annFilter, cardinality, k);
181+
stopStopWatchAndLog(annStopWatch, "ANN search", segmentName);
171182

172183
// See whether we have to perform exact search based on approx search results
173184
// This is required if there are no native engine files or if approximate search returned
@@ -180,6 +191,14 @@ public PerLeafResult searchLeaf(LeafReaderContext context, int k) throws IOExcep
180191
return new PerLeafResult(filterWeight == null ? null : filterBitSet, docIdsToScoreMap);
181192
}
182193

194+
private void stopStopWatchAndLog(@Nullable final StopWatch stopWatch, final String prefixMessage, String segmentName) {
195+
if (log.isDebugEnabled() && stopWatch != null) {
196+
stopWatch.stop();
197+
final String logMessage = prefixMessage + " shard: [{}], segment: [{}], field: [{}], time in nanos:[{}] ";
198+
log.debug(logMessage, knnQuery.getShardId(), segmentName, knnQuery.getField(), stopWatch.totalTime().nanos());
199+
}
200+
}
201+
183202
private BitSet getFilteredDocsBitSet(final LeafReaderContext ctx) throws IOException {
184203
if (this.filterWeight == null) {
185204
return new FixedBitSet(0);
@@ -236,7 +255,7 @@ private Map<Integer, Float> doExactSearch(
236255
final LeafReaderContext context,
237256
final DocIdSetIterator acceptedDocs,
238257
final long numberOfAcceptedDocs,
239-
int k
258+
final int k
240259
) throws IOException {
241260
final ExactSearcherContextBuilder exactSearcherContextBuilder = ExactSearcher.ExactSearcherContext.builder()
242261
.isParentHits(true)
@@ -251,13 +270,12 @@ private Map<Integer, Float> doExactSearch(
251270
}
252271

253272
private Map<Integer, Float> doANNSearch(
273+
final SegmentReader reader,
254274
final LeafReaderContext context,
255275
final BitSet filterIdsBitSet,
256276
final int cardinality,
257277
final int k
258278
) throws IOException {
259-
final SegmentReader reader = Lucene.segmentReader(context.reader());
260-
261279
FieldInfo fieldInfo = FieldInfoExtractor.getFieldInfo(reader, knnQuery.getField());
262280

263281
if (fieldInfo == null) {
@@ -416,7 +434,11 @@ public Map<Integer, Float> exactSearch(
416434
final LeafReaderContext leafReaderContext,
417435
final ExactSearcher.ExactSearcherContext exactSearcherContext
418436
) throws IOException {
419-
return exactSearcher.searchLeaf(leafReaderContext, exactSearcherContext);
437+
StopWatch stopWatch = startStopWatch();
438+
Map<Integer, Float> exactSearchResults = exactSearcher.searchLeaf(leafReaderContext, exactSearcherContext);
439+
final SegmentReader reader = Lucene.segmentReader(leafReaderContext.reader());
440+
stopStopWatchAndLog(stopWatch, "Exact search", reader.getSegmentName());
441+
return exactSearchResults;
420442
}
421443

422444
@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)