mirror of
https://github.com/MarginaliaSearch/MarginaliaSearch.git
synced 2025-10-05 21:22:39 +02:00
(index) Add performance metrics
This commit is contained in:
@@ -223,7 +223,7 @@ public class PerfTestMain {
|
|||||||
int iter;
|
int iter;
|
||||||
for (iter = 0;; iter++) {
|
for (iter = 0;; iter++) {
|
||||||
SearchParameters searchParameters = new SearchParameters(parsedQuery, new SearchSetAny());
|
SearchParameters searchParameters = new SearchParameters(parsedQuery, new SearchSetAny());
|
||||||
var execution = new IndexQueryExecution(searchParameters, rankingService, indexReader);
|
var execution = new IndexQueryExecution(searchParameters, 1, rankingService, indexReader);
|
||||||
long start = System.nanoTime();
|
long start = System.nanoTime();
|
||||||
execution.run();
|
execution.run();
|
||||||
long end = System.nanoTime();
|
long end = System.nanoTime();
|
||||||
|
@@ -71,9 +71,8 @@ public class IndexGrpcService
|
|||||||
private final SearchSetsService searchSetsService;
|
private final SearchSetsService searchSetsService;
|
||||||
|
|
||||||
private final IndexResultRankingService rankingService;
|
private final IndexResultRankingService rankingService;
|
||||||
|
|
||||||
private final String nodeName;
|
private final String nodeName;
|
||||||
|
private final int nodeId;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public IndexGrpcService(ServiceConfiguration serviceConfiguration,
|
public IndexGrpcService(ServiceConfiguration serviceConfiguration,
|
||||||
@@ -81,7 +80,7 @@ public class IndexGrpcService
|
|||||||
SearchSetsService searchSetsService,
|
SearchSetsService searchSetsService,
|
||||||
IndexResultRankingService rankingService)
|
IndexResultRankingService rankingService)
|
||||||
{
|
{
|
||||||
var nodeId = serviceConfiguration.node();
|
this.nodeId = serviceConfiguration.node();
|
||||||
this.nodeName = Integer.toString(nodeId);
|
this.nodeName = Integer.toString(nodeId);
|
||||||
this.statefulIndex = statefulIndex;
|
this.statefulIndex = statefulIndex;
|
||||||
this.searchSetsService = searchSetsService;
|
this.searchSetsService = searchSetsService;
|
||||||
@@ -108,7 +107,7 @@ public class IndexGrpcService
|
|||||||
return List.of();
|
return List.of();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new IndexQueryExecution(params, rankingService, statefulIndex.get()).run();
|
return new IndexQueryExecution(params, nodeId, rankingService, statefulIndex.get()).run();
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
logger.error("Error in handling request", ex);
|
logger.error("Error in handling request", ex);
|
||||||
@@ -149,7 +148,7 @@ public class IndexGrpcService
|
|||||||
return List.of();
|
return List.of();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new IndexQueryExecution(new SearchParameters(specsSet, getSearchSet(specsSet)), rankingService, statefulIndex.get()).run();
|
return new IndexQueryExecution(new SearchParameters(specsSet, getSearchSet(specsSet)), 1, rankingService, statefulIndex.get()).run();
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
logger.error("Error in handling request", ex);
|
logger.error("Error in handling request", ex);
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
package nu.marginalia.index;
|
package nu.marginalia.index;
|
||||||
|
|
||||||
|
import io.prometheus.client.Gauge;
|
||||||
import nu.marginalia.api.searchquery.RpcDecoratedResultItem;
|
import nu.marginalia.api.searchquery.RpcDecoratedResultItem;
|
||||||
import nu.marginalia.array.page.LongQueryBuffer;
|
import nu.marginalia.array.page.LongQueryBuffer;
|
||||||
import nu.marginalia.index.index.CombinedIndexReader;
|
import nu.marginalia.index.index.CombinedIndexReader;
|
||||||
@@ -19,7 +20,6 @@ import java.util.ArrayList;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
|
||||||
|
|
||||||
/** Performs an index query */
|
/** Performs an index query */
|
||||||
public class IndexQueryExecution {
|
public class IndexQueryExecution {
|
||||||
@@ -35,49 +35,60 @@ public class IndexQueryExecution {
|
|||||||
// operations per lookup and again optimize tail latency
|
// operations per lookup and again optimize tail latency
|
||||||
private static final int lookupBatchSize = SkipListConstants.BLOCK_SIZE / 16;
|
private static final int lookupBatchSize = SkipListConstants.BLOCK_SIZE / 16;
|
||||||
|
|
||||||
private static final AtomicLong lookupTime = new AtomicLong();
|
|
||||||
private static final AtomicLong prepTime = new AtomicLong();
|
|
||||||
private static final AtomicLong valuationTime = new AtomicLong();
|
|
||||||
|
|
||||||
private static final ExecutorService threadPool = new ThreadPoolExecutor(indexValuationThreads, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<>());
|
private static final ExecutorService threadPool = new ThreadPoolExecutor(indexValuationThreads, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<>());
|
||||||
private static final Logger log = LoggerFactory.getLogger(IndexQueryExecution.class);
|
private static final Logger log = LoggerFactory.getLogger(IndexQueryExecution.class);
|
||||||
|
|
||||||
|
private final String nodeName;
|
||||||
private final IndexResultRankingService rankingService;
|
private final IndexResultRankingService rankingService;
|
||||||
|
|
||||||
private final ResultRankingContext rankingContext;
|
private final ResultRankingContext rankingContext;
|
||||||
private final List<IndexQuery> queries;
|
private final List<IndexQuery> queries;
|
||||||
private final IndexSearchBudget budget;
|
private final IndexSearchBudget budget;
|
||||||
private final ResultPriorityQueue resultHeap;
|
private final ResultPriorityQueue resultHeap;
|
||||||
|
|
||||||
private final CountDownLatch lookupCountdown;
|
private final CountDownLatch lookupCountdown;
|
||||||
private final CountDownLatch preparationCountdown;
|
private final CountDownLatch preparationCountdown;
|
||||||
private final CountDownLatch rankingCountdown;
|
private final CountDownLatch rankingCountdown;
|
||||||
|
|
||||||
private final ArrayBlockingQueue<CombinedDocIdList> fullPreparationQueue = new ArrayBlockingQueue<>(8, true);
|
private final ArrayBlockingQueue<CombinedDocIdList> fullPreparationQueue = new ArrayBlockingQueue<>(1);
|
||||||
private final ArrayBlockingQueue<CombinedDocIdList> priorityPreparationQueue = new ArrayBlockingQueue<>(8, true);
|
private final ArrayBlockingQueue<CombinedDocIdList> priorityPreparationQueue = new ArrayBlockingQueue<>(1);
|
||||||
private final ArrayBlockingQueue<IndexResultRankingService.RankingData> fullEvaluationQueue = new ArrayBlockingQueue<>(8, true);
|
private final ArrayBlockingQueue<IndexResultRankingService.RankingData> fullEvaluationQueue = new ArrayBlockingQueue<>(4);
|
||||||
private final ArrayBlockingQueue<IndexResultRankingService.RankingData> priorityEvaluationQueue = new ArrayBlockingQueue<>(8, true);
|
private final ArrayBlockingQueue<IndexResultRankingService.RankingData> priorityEvaluationQueue = new ArrayBlockingQueue<>(4);
|
||||||
|
|
||||||
private final int limitTotal;
|
private final int limitTotal;
|
||||||
private final int limitByDomain;
|
private final int limitByDomain;
|
||||||
|
|
||||||
static {
|
private static final Gauge metric_index_lookup_time_s = Gauge.build()
|
||||||
Thread.ofPlatform().daemon().start(() -> {
|
.labelNames("node")
|
||||||
for (;;) {
|
.name("index_exec_lookup_time_s")
|
||||||
try {
|
.help("Time in query spent on lookups")
|
||||||
TimeUnit.SECONDS.sleep(10);
|
.register();
|
||||||
}
|
|
||||||
catch (InterruptedException e) {
|
private static final Gauge metric_index_prep_time_s = Gauge.build()
|
||||||
e.printStackTrace();
|
.labelNames("node")
|
||||||
break;
|
.name("index_exec_prep_time_s")
|
||||||
}
|
.help("Time in query spent retrieving positions and spans")
|
||||||
log.info("Lookup: {}, Valuation: {}, Prep Time: {}", lookupTime.get() / 1_000_000_000., valuationTime.get() / 1_000_000_000., prepTime.get() / 1_000_000_000.);
|
.register();
|
||||||
}
|
|
||||||
});
|
private static final Gauge metric_index_rank_time_s = Gauge.build()
|
||||||
}
|
.labelNames("node")
|
||||||
|
.name("index_exec_ranking_time_s")
|
||||||
|
.help("Time in query spent on ranking")
|
||||||
|
.register();
|
||||||
|
|
||||||
|
private static final Gauge metric_index_documents_ranked = Gauge.build()
|
||||||
|
.labelNames("node")
|
||||||
|
.name("index_exec_documents_ranked")
|
||||||
|
.help("Number of documents ranked")
|
||||||
|
.register();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public IndexQueryExecution(SearchParameters params,
|
public IndexQueryExecution(SearchParameters params,
|
||||||
|
int serviceNode,
|
||||||
IndexResultRankingService rankingService,
|
IndexResultRankingService rankingService,
|
||||||
CombinedIndexReader currentIndex) {
|
CombinedIndexReader currentIndex) {
|
||||||
|
this.nodeName = Integer.toString(serviceNode);
|
||||||
this.rankingService = rankingService;
|
this.rankingService = rankingService;
|
||||||
|
|
||||||
resultHeap = new ResultPriorityQueue(params.fetchSize);
|
resultHeap = new ResultPriorityQueue(params.fetchSize);
|
||||||
@@ -123,6 +134,10 @@ public class IndexQueryExecution {
|
|||||||
data.close();
|
data.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
metric_index_documents_ranked
|
||||||
|
.labels(nodeName)
|
||||||
|
.inc(resultHeap.getItemsProcessed());
|
||||||
|
|
||||||
// Final result selection
|
// Final result selection
|
||||||
return rankingService.selectBestResults(limitByDomain, limitTotal, rankingContext, resultHeap.toList());
|
return rankingService.selectBestResults(limitByDomain, limitTotal, rankingContext, resultHeap.toList());
|
||||||
}
|
}
|
||||||
@@ -138,7 +153,9 @@ public class IndexQueryExecution {
|
|||||||
long st = System.nanoTime();
|
long st = System.nanoTime();
|
||||||
query.getMoreResults(buffer);
|
query.getMoreResults(buffer);
|
||||||
long et = System.nanoTime();
|
long et = System.nanoTime();
|
||||||
lookupTime.addAndGet(et - st);
|
metric_index_lookup_time_s
|
||||||
|
.labels(nodeName)
|
||||||
|
.inc((et - st)/1_000_000_000.);
|
||||||
|
|
||||||
if (buffer.isEmpty())
|
if (buffer.isEmpty())
|
||||||
continue;
|
continue;
|
||||||
@@ -181,10 +198,14 @@ public class IndexQueryExecution {
|
|||||||
while (budget.hasTimeLeft() && (lookupCountdown.getCount() > 0 || !inputQueue.isEmpty())) {
|
while (budget.hasTimeLeft() && (lookupCountdown.getCount() > 0 || !inputQueue.isEmpty())) {
|
||||||
var docIds = inputQueue.poll(Math.clamp(budget.timeLeft(), 1, 5), TimeUnit.MILLISECONDS);
|
var docIds = inputQueue.poll(Math.clamp(budget.timeLeft(), 1, 5), TimeUnit.MILLISECONDS);
|
||||||
if (docIds == null) continue;
|
if (docIds == null) continue;
|
||||||
|
|
||||||
long st = System.nanoTime();
|
long st = System.nanoTime();
|
||||||
var preparedData = rankingService.prepareRankingData(rankingContext, docIds, budget);
|
var preparedData = rankingService.prepareRankingData(rankingContext, docIds, budget);
|
||||||
long et = System.nanoTime();
|
long et = System.nanoTime();
|
||||||
prepTime.addAndGet(et - st);
|
metric_index_prep_time_s
|
||||||
|
.labels(nodeName)
|
||||||
|
.inc((et - st)/1_000_000_000.);
|
||||||
|
|
||||||
if (!outputQueue.offer(preparedData, Math.max(1, budget.timeLeft()), TimeUnit.MILLISECONDS))
|
if (!outputQueue.offer(preparedData, Math.max(1, budget.timeLeft()), TimeUnit.MILLISECONDS))
|
||||||
preparedData.close();
|
preparedData.close();
|
||||||
}
|
}
|
||||||
@@ -209,7 +230,10 @@ public class IndexQueryExecution {
|
|||||||
long st = System.nanoTime();
|
long st = System.nanoTime();
|
||||||
resultHeap.addAll(rankingService.rankResults(budget, rankingContext, rankingData, false));
|
resultHeap.addAll(rankingService.rankResults(budget, rankingContext, rankingData, false));
|
||||||
long et = System.nanoTime();
|
long et = System.nanoTime();
|
||||||
valuationTime.addAndGet(et - st);
|
|
||||||
|
metric_index_rank_time_s
|
||||||
|
.labels(nodeName)
|
||||||
|
.inc((et - st)/1_000_000_000.);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
|
@@ -80,8 +80,8 @@ class CrawlerRetreiverTest {
|
|||||||
var specs = CrawlerMain.CrawlSpecRecord
|
var specs = CrawlerMain.CrawlSpecRecord
|
||||||
.builder()
|
.builder()
|
||||||
.crawlDepth(5)
|
.crawlDepth(5)
|
||||||
.domain("www.marginalia.nu")
|
.domain("thenewleafjournal.com")
|
||||||
.urls(List.of("https://www.marginalia.nu/misc/debian-laptop-install-log/"))
|
.urls(List.of("https://thenewleafjournal.com/"))
|
||||||
.build();
|
.build();
|
||||||
Path tempFile = null;
|
Path tempFile = null;
|
||||||
try {
|
try {
|
||||||
|
@@ -224,7 +224,7 @@ public class IntegrationTest {
|
|||||||
|
|
||||||
System.out.println(indexRequest);
|
System.out.println(indexRequest);
|
||||||
|
|
||||||
var rs = new IndexQueryExecution(new SearchParameters(indexRequest, new SearchSetAny()), rankingService, statefulIndex.get());
|
var rs = new IndexQueryExecution(new SearchParameters(indexRequest, new SearchSetAny()), 1, rankingService, statefulIndex.get());
|
||||||
|
|
||||||
System.out.println(rs);
|
System.out.println(rs);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user