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:
@@ -56,8 +56,10 @@ export class ComparePerformanceView extends AbstractWebview<
|
|||||||
}
|
}
|
||||||
|
|
||||||
const [fromPerf, toPerf] = await Promise.all([
|
const [fromPerf, toPerf] = await Promise.all([
|
||||||
scanLogWithProgress(fromJsonLog, "1/2"),
|
fromJsonLog === ""
|
||||||
scanLogWithProgress(toJsonLog, "2/2"),
|
? new PerformanceOverviewScanner()
|
||||||
|
: scanLogWithProgress(fromJsonLog, "1/2"),
|
||||||
|
scanLogWithProgress(toJsonLog, fromJsonLog === "" ? "1/1" : "2/2"),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await this.postMessage({
|
await this.postMessage({
|
||||||
|
|||||||
@@ -927,7 +927,7 @@ async function activateWithInstalledDistribution(
|
|||||||
): Promise<void> => showResultsForComparison(compareView, from, to),
|
): Promise<void> => showResultsForComparison(compareView, from, to),
|
||||||
async (
|
async (
|
||||||
from: CompletedLocalQueryInfo,
|
from: CompletedLocalQueryInfo,
|
||||||
to: CompletedLocalQueryInfo,
|
to: CompletedLocalQueryInfo | undefined,
|
||||||
): Promise<void> =>
|
): Promise<void> =>
|
||||||
showPerformanceComparison(comparePerformanceView, from, to),
|
showPerformanceComparison(comparePerformanceView, from, to),
|
||||||
);
|
);
|
||||||
@@ -1208,17 +1208,22 @@ async function showResultsForComparison(
|
|||||||
async function showPerformanceComparison(
|
async function showPerformanceComparison(
|
||||||
view: ComparePerformanceView,
|
view: ComparePerformanceView,
|
||||||
from: CompletedLocalQueryInfo,
|
from: CompletedLocalQueryInfo,
|
||||||
to: CompletedLocalQueryInfo,
|
to: CompletedLocalQueryInfo | undefined,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const fromLog = from.evaluatorLogPaths?.jsonSummary;
|
let fromLog = from.evaluatorLogPaths?.jsonSummary;
|
||||||
const toLog = to.evaluatorLogPaths?.jsonSummary;
|
let toLog = to?.evaluatorLogPaths?.jsonSummary;
|
||||||
|
|
||||||
|
if (to === undefined) {
|
||||||
|
toLog = fromLog;
|
||||||
|
fromLog = "";
|
||||||
|
}
|
||||||
if (fromLog === undefined || toLog === undefined) {
|
if (fromLog === undefined || toLog === undefined) {
|
||||||
return extLogger.showWarningMessage(
|
return extLogger.showWarningMessage(
|
||||||
`Cannot compare performance as the structured logs are missing. Did they queries complete normally?`,
|
`Cannot compare performance as the structured logs are missing. Did they queries complete normally?`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
await extLogger.log(
|
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);
|
await view.showResults(fromLog, toLog);
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ export class QueryHistoryManager extends DisposableObject {
|
|||||||
) => Promise<void>,
|
) => Promise<void>,
|
||||||
private readonly doComparePerformanceCallback: (
|
private readonly doComparePerformanceCallback: (
|
||||||
from: CompletedLocalQueryInfo,
|
from: CompletedLocalQueryInfo,
|
||||||
to: CompletedLocalQueryInfo,
|
to: CompletedLocalQueryInfo | undefined,
|
||||||
) => Promise<void>,
|
) => Promise<void>,
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
@@ -706,7 +706,10 @@ export class QueryHistoryManager extends DisposableObject {
|
|||||||
|
|
||||||
let toItem: CompletedLocalQueryInfo | undefined = undefined;
|
let toItem: CompletedLocalQueryInfo | undefined = undefined;
|
||||||
try {
|
try {
|
||||||
toItem = await this.findOtherQueryToCompare(fromItem, multiSelect);
|
toItem = await this.findOtherQueryToComparePerformance(
|
||||||
|
fromItem,
|
||||||
|
multiSelect,
|
||||||
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
void showAndLogErrorMessage(
|
void showAndLogErrorMessage(
|
||||||
this.app.logger,
|
this.app.logger,
|
||||||
@@ -714,9 +717,7 @@ export class QueryHistoryManager extends DisposableObject {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (toItem !== undefined) {
|
await this.doComparePerformanceCallback(fromItem, toItem);
|
||||||
await this.doComparePerformanceCallback(fromItem, toItem);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async handleItemClicked(item: QueryHistoryInfo) {
|
async handleItemClicked(item: QueryHistoryInfo) {
|
||||||
@@ -1116,6 +1117,7 @@ export class QueryHistoryManager extends DisposableObject {
|
|||||||
detail: item.completedQuery.message,
|
detail: item.completedQuery.message,
|
||||||
query: item,
|
query: item,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
if (comparableQueryLabels.length < 1) {
|
if (comparableQueryLabels.length < 1) {
|
||||||
throw new Error("No other queries available to compare with.");
|
throw new Error("No other queries available to compare with.");
|
||||||
}
|
}
|
||||||
@@ -1124,6 +1126,60 @@ export class QueryHistoryManager extends DisposableObject {
|
|||||||
return choice?.query;
|
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
|
* 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
|
* when exactly 2 queries are selected always have the proper _from_ query. Always use
|
||||||
|
|||||||
Reference in New Issue
Block a user