compare-perf: Add support for selecting a single run as input

A very hacky implementation that simply instantiates an empty
`PerformanceOverviewScanner` as the "from" column (i.e. with all values
empty). To see it in action, select a single query run in the query
history and pick "Compare Performance" from the context menu. Then
select the "Single run" option when prompted.
This commit is contained in:
Taus
2024-11-14 21:08:15 +00:00
committed by Asger F
parent 412338c717
commit 6d4427e59c
3 changed files with 75 additions and 12 deletions

View File

@@ -56,8 +56,10 @@ export class ComparePerformanceView extends AbstractWebview<
}
const [fromPerf, toPerf] = await Promise.all([
scanLogWithProgress(fromJsonLog, "1/2"),
scanLogWithProgress(toJsonLog, "2/2"),
fromJsonLog === ""
? new PerformanceOverviewScanner()
: scanLogWithProgress(fromJsonLog, "1/2"),
scanLogWithProgress(toJsonLog, fromJsonLog === "" ? "1/1" : "2/2"),
]);
await this.postMessage({

View File

@@ -927,7 +927,7 @@ async function activateWithInstalledDistribution(
): Promise<void> => showResultsForComparison(compareView, from, to),
async (
from: CompletedLocalQueryInfo,
to: CompletedLocalQueryInfo,
to: CompletedLocalQueryInfo | undefined,
): Promise<void> =>
showPerformanceComparison(comparePerformanceView, from, to),
);
@@ -1208,17 +1208,22 @@ async function showResultsForComparison(
async function showPerformanceComparison(
view: ComparePerformanceView,
from: CompletedLocalQueryInfo,
to: CompletedLocalQueryInfo,
to: CompletedLocalQueryInfo | undefined,
): Promise<void> {
const fromLog = from.evaluatorLogPaths?.jsonSummary;
const toLog = to.evaluatorLogPaths?.jsonSummary;
let fromLog = from.evaluatorLogPaths?.jsonSummary;
let toLog = to?.evaluatorLogPaths?.jsonSummary;
if (to === undefined) {
toLog = fromLog;
fromLog = "";
}
if (fromLog === undefined || toLog === undefined) {
return extLogger.showWarningMessage(
`Cannot compare performance as the structured logs are missing. Did they queries complete normally?`,
);
}
await extLogger.log(
`Comparing performance of ${from.getQueryName()} and ${to.getQueryName()}`,
`Comparing performance of ${from.getQueryName()} and ${to?.getQueryName() ?? "baseline"}`,
);
await view.showResults(fromLog, toLog);

View File

@@ -151,7 +151,7 @@ export class QueryHistoryManager extends DisposableObject {
) => Promise<void>,
private readonly doComparePerformanceCallback: (
from: CompletedLocalQueryInfo,
to: CompletedLocalQueryInfo,
to: CompletedLocalQueryInfo | undefined,
) => Promise<void>,
) {
super();
@@ -706,7 +706,10 @@ export class QueryHistoryManager extends DisposableObject {
let toItem: CompletedLocalQueryInfo | undefined = undefined;
try {
toItem = await this.findOtherQueryToCompare(fromItem, multiSelect);
toItem = await this.findOtherQueryToComparePerformance(
fromItem,
multiSelect,
);
} catch (e) {
void showAndLogErrorMessage(
this.app.logger,
@@ -714,10 +717,8 @@ export class QueryHistoryManager extends DisposableObject {
);
}
if (toItem !== undefined) {
await this.doComparePerformanceCallback(fromItem, toItem);
}
}
async handleItemClicked(item: QueryHistoryInfo) {
this.treeDataProvider.setCurrentItem(item);
@@ -1116,6 +1117,7 @@ export class QueryHistoryManager extends DisposableObject {
detail: item.completedQuery.message,
query: item,
}));
if (comparableQueryLabels.length < 1) {
throw new Error("No other queries available to compare with.");
}
@@ -1124,6 +1126,60 @@ export class QueryHistoryManager extends DisposableObject {
return choice?.query;
}
private async findOtherQueryToComparePerformance(
fromItem: CompletedLocalQueryInfo,
allSelectedItems: CompletedLocalQueryInfo[],
): Promise<CompletedLocalQueryInfo | undefined> {
const dbName = fromItem.databaseName;
// If exactly 2 items are selected, return the one that
// isn't being used as the "from" item.
if (allSelectedItems.length === 2) {
const otherItem =
fromItem === allSelectedItems[0]
? allSelectedItems[1]
: allSelectedItems[0];
if (otherItem.databaseName !== dbName) {
throw new Error("Query databases must be the same.");
}
return otherItem;
}
if (allSelectedItems.length > 2) {
throw new Error("Please select no more than 2 queries.");
}
// Otherwise, present a dialog so the user can choose the item they want to use.
const comparableQueryLabels = this.treeDataProvider.allHistory
.filter(this.isSuccessfulCompletedLocalQueryInfo)
.filter(
(otherItem) =>
otherItem !== fromItem && otherItem.databaseName === dbName,
)
.map((item) => ({
label: this.labelProvider.getLabel(item),
description: item.databaseName,
detail: item.completedQuery.message,
query: item,
}));
const comparableQueryLabelsWithDefault = [
{
label: "Single run",
description:
"Look at the performance of this run, compared to a trivial baseline",
detail: undefined,
query: undefined,
},
...comparableQueryLabels,
];
if (comparableQueryLabelsWithDefault.length < 1) {
throw new Error("No other queries available to compare with.");
}
const choice = await window.showQuickPick(comparableQueryLabelsWithDefault);
return choice?.query;
}
/**
* Updates the compare with source query. This ensures that all compare command invocations
* when exactly 2 queries are selected always have the proper _from_ query. Always use