Skip to content

Commit 8b2f378

Browse files
committed
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.
1 parent e25b2b1 commit 8b2f378

File tree

3 files changed

+76
-14
lines changed

3 files changed

+76
-14
lines changed

extensions/ql-vscode/src/compare-performance/compare-performance-view.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,11 @@ export class ComparePerformanceView extends AbstractWebview<
6868
await this.waitForPanelLoaded();
6969

7070
// TODO: try processing in (async) parallel once readJsonl is streaming
71-
const fromPerf = await scanLog(
72-
fromJsonLog,
73-
new PerformanceOverviewScanner(),
74-
);
71+
const fromPerf =
72+
fromJsonLog === ""
73+
? new PerformanceOverviewScanner()
74+
: await scanLog(fromJsonLog, new PerformanceOverviewScanner());
75+
7576
const toPerf = await scanLog(toJsonLog, new PerformanceOverviewScanner());
7677

7778
// TODO: filter out irrelevant common predicates before transfer?

extensions/ql-vscode/src/extension.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -927,7 +927,7 @@ async function activateWithInstalledDistribution(
927927
): Promise<void> => showResultsForComparison(compareView, from, to),
928928
async (
929929
from: CompletedLocalQueryInfo,
930-
to: CompletedLocalQueryInfo,
930+
to: CompletedLocalQueryInfo | undefined,
931931
): Promise<void> =>
932932
showPerformanceComparison(comparePerformanceView, from, to),
933933
);
@@ -1210,17 +1210,22 @@ async function showResultsForComparison(
12101210
async function showPerformanceComparison(
12111211
view: ComparePerformanceView,
12121212
from: CompletedLocalQueryInfo,
1213-
to: CompletedLocalQueryInfo,
1213+
to: CompletedLocalQueryInfo | undefined,
12141214
): Promise<void> {
1215-
const fromLog = from.evalutorLogPaths?.jsonSummary;
1216-
const toLog = to.evalutorLogPaths?.jsonSummary;
1215+
let fromLog = from.evalutorLogPaths?.jsonSummary;
1216+
let toLog = to?.evalutorLogPaths?.jsonSummary;
1217+
1218+
if (to === undefined) {
1219+
toLog = fromLog;
1220+
fromLog = "";
1221+
}
12171222
if (fromLog === undefined || toLog === undefined) {
12181223
return extLogger.showWarningMessage(
12191224
`Cannot compare performance as the structured logs are missing. Did they queries complete normally?`,
12201225
);
12211226
}
12221227
await extLogger.log(
1223-
`Comparing performance of ${from.getQueryName()} and ${to.getQueryName()}`,
1228+
`Comparing performance of ${from.getQueryName()} and ${to?.getQueryName() ?? "baseline"}`,
12241229
);
12251230

12261231
await view.showResults(fromLog, toLog);

extensions/ql-vscode/src/query-history/query-history-manager.ts

Lines changed: 61 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ export class QueryHistoryManager extends DisposableObject {
151151
) => Promise<void>,
152152
private readonly doComparePerformanceCallback: (
153153
from: CompletedLocalQueryInfo,
154-
to: CompletedLocalQueryInfo,
154+
to: CompletedLocalQueryInfo | undefined,
155155
) => Promise<void>,
156156
) {
157157
super();
@@ -706,17 +706,18 @@ export class QueryHistoryManager extends DisposableObject {
706706

707707
let toItem: CompletedLocalQueryInfo | undefined = undefined;
708708
try {
709-
toItem = await this.findOtherQueryToCompare(fromItem, multiSelect);
709+
toItem = await this.findOtherQueryToComparePerformance(
710+
fromItem,
711+
multiSelect,
712+
);
710713
} catch (e) {
711714
void showAndLogErrorMessage(
712715
this.app.logger,
713716
`Failed to compare queries: ${getErrorMessage(e)}`,
714717
);
715718
}
716719

717-
if (toItem !== undefined) {
718-
await this.doComparePerformanceCallback(fromItem, toItem);
719-
}
720+
await this.doComparePerformanceCallback(fromItem, toItem);
720721
}
721722

722723
async handleItemClicked(item: QueryHistoryInfo) {
@@ -1116,6 +1117,7 @@ export class QueryHistoryManager extends DisposableObject {
11161117
detail: item.completedQuery.message,
11171118
query: item,
11181119
}));
1120+
11191121
if (comparableQueryLabels.length < 1) {
11201122
throw new Error("No other queries available to compare with.");
11211123
}
@@ -1124,6 +1126,60 @@ export class QueryHistoryManager extends DisposableObject {
11241126
return choice?.query;
11251127
}
11261128

1129+
private async findOtherQueryToComparePerformance(
1130+
fromItem: CompletedLocalQueryInfo,
1131+
allSelectedItems: CompletedLocalQueryInfo[],
1132+
): Promise<CompletedLocalQueryInfo | undefined> {
1133+
const dbName = fromItem.databaseName;
1134+
1135+
// If exactly 2 items are selected, return the one that
1136+
// isn't being used as the "from" item.
1137+
if (allSelectedItems.length === 2) {
1138+
const otherItem =
1139+
fromItem === allSelectedItems[0]
1140+
? allSelectedItems[1]
1141+
: allSelectedItems[0];
1142+
if (otherItem.databaseName !== dbName) {
1143+
throw new Error("Query databases must be the same.");
1144+
}
1145+
return otherItem;
1146+
}
1147+
1148+
if (allSelectedItems.length > 2) {
1149+
throw new Error("Please select no more than 2 queries.");
1150+
}
1151+
1152+
// Otherwise, present a dialog so the user can choose the item they want to use.
1153+
const comparableQueryLabels = this.treeDataProvider.allHistory
1154+
.filter(this.isSuccessfulCompletedLocalQueryInfo)
1155+
.filter(
1156+
(otherItem) =>
1157+
otherItem !== fromItem && otherItem.databaseName === dbName,
1158+
)
1159+
.map((item) => ({
1160+
label: this.labelProvider.getLabel(item),
1161+
description: item.databaseName,
1162+
detail: item.completedQuery.message,
1163+
query: item,
1164+
}));
1165+
const comparableQueryLabelsWithDefault = [
1166+
{
1167+
label: "Single run",
1168+
description:
1169+
"Look at the performance of this run, compared to a trivial baseline",
1170+
detail: undefined,
1171+
query: undefined,
1172+
},
1173+
...comparableQueryLabels,
1174+
];
1175+
if (comparableQueryLabelsWithDefault.length < 1) {
1176+
throw new Error("No other queries available to compare with.");
1177+
}
1178+
const choice = await window.showQuickPick(comparableQueryLabelsWithDefault);
1179+
1180+
return choice?.query;
1181+
}
1182+
11271183
/**
11281184
* Updates the compare with source query. This ensures that all compare command invocations
11291185
* when exactly 2 queries are selected always have the proper _from_ query. Always use

0 commit comments

Comments
 (0)