Skip to content

Commit 07e9e44

Browse files
alexetaeisenberg
andauthored
Add cache of query schemas to results view (#3862)
* Add cache of query schemas to results view * Update changelog * Don't call bqrsInfo with a page size of 0 * Update extensions/ql-vscode/CHANGELOG.md Co-authored-by: Andrew Eisenberg <[email protected]> --------- Co-authored-by: Andrew Eisenberg <[email protected]>
1 parent 2c7021b commit 07e9e44

File tree

4 files changed

+31
-2
lines changed

4 files changed

+31
-2
lines changed

extensions/ql-vscode/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
- Add a palette command that allows importing all databases directly inside of a parent folder. [#3797](https://github.com/github/vscode-codeql/pull/3797)
66
- Only use VS Code telemetry settings instead of using `codeQL.telemetry.enableTelemetry` [#3853](https://github.com/github/vscode-codeql/pull/3853)
7+
- Improve the performance of the results view with large numbers of results. [#3862](https://github.com/github/vscode-codeql/pull/3862)
78

89
## 1.16.1 - 6 November 2024
910

extensions/ql-vscode/src/language-support/contextual/cached-operation.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export class CachedOperation<S extends unknown[], U> {
77
private readonly operation: (t: string, ...args: S) => Promise<U>;
88
private readonly cached: Map<string, U>;
99
private readonly lru: string[];
10+
private generation: number;
1011
private readonly inProgressCallbacks: Map<
1112
string,
1213
Array<[(u: U) => void, (reason?: Error) => void]>
@@ -17,6 +18,7 @@ export class CachedOperation<S extends unknown[], U> {
1718
private cacheSize = 100,
1819
) {
1920
this.operation = operation;
21+
this.generation = 0;
2022
this.lru = [];
2123
this.inProgressCallbacks = new Map<
2224
string,
@@ -46,14 +48,19 @@ export class CachedOperation<S extends unknown[], U> {
4648
inProgressCallback.push([resolve, reject]);
4749
});
4850
}
49-
51+
const origGeneration = this.generation;
5052
// Otherwise compute the new value, but leave a callback to allow sharing work
5153
const callbacks: Array<[(u: U) => void, (reason?: Error) => void]> = [];
5254
this.inProgressCallbacks.set(t, callbacks);
5355
try {
5456
const result = await this.operation(t, ...args);
5557
callbacks.forEach((f) => f[0](result));
5658
this.inProgressCallbacks.delete(t);
59+
if (this.generation !== origGeneration) {
60+
// Cache was reset in the meantime so don't trust this
61+
// result enough to cache it.
62+
return result;
63+
}
5764
if (this.lru.length > this.cacheSize) {
5865
const toRemove = this.lru.shift()!;
5966
this.cached.delete(toRemove);
@@ -69,4 +76,11 @@ export class CachedOperation<S extends unknown[], U> {
6976
this.inProgressCallbacks.delete(t);
7077
}
7178
}
79+
80+
reset() {
81+
this.cached.clear();
82+
this.lru.length = 0;
83+
this.generation++;
84+
this.inProgressCallbacks.clear();
85+
}
7286
}

extensions/ql-vscode/src/local-queries/results-view.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ import type { App } from "../common/app";
7575
import type { Disposable } from "../common/disposable-object";
7676
import type { RawResultSet } from "../common/raw-result-types";
7777
import type { BqrsResultSetSchema } from "../common/bqrs-cli-types";
78+
import { CachedOperation } from "../language-support/contextual/cached-operation";
7879

7980
/**
8081
* results-view.ts
@@ -177,6 +178,8 @@ export class ResultsView extends AbstractWebview<
177178
// Event listeners that should be disposed of when the view is disposed.
178179
private disposableEventListeners: Disposable[] = [];
179180

181+
private schemaCache: CachedOperation<[], BqrsResultSetSchema[]>;
182+
180183
constructor(
181184
app: App,
182185
private databaseManager: DatabaseManager,
@@ -206,6 +209,10 @@ export class ResultsView extends AbstractWebview<
206209
}
207210
}),
208211
);
212+
213+
this.schemaCache = new CachedOperation(
214+
this.getResultSetSchemasImpl.bind(this),
215+
);
209216
}
210217

211218
public getCommands(): ResultsViewCommands {
@@ -420,6 +427,7 @@ export class ResultsView extends AbstractWebview<
420427
);
421428
return;
422429
}
430+
this.schemaCache.reset();
423431
// Notify the webview that it should expect new results.
424432
await this.postMessage({ t: "resultsUpdating" });
425433
await this._displayedQuery.completedQuery.updateSortState(
@@ -610,6 +618,12 @@ export class ResultsView extends AbstractWebview<
610618
selectedTable = "",
611619
): Promise<BqrsResultSetSchema[]> {
612620
const resultsPath = completedQuery.getResultsPath(selectedTable);
621+
return this.schemaCache.get(resultsPath);
622+
}
623+
624+
private async getResultSetSchemasImpl(
625+
resultsPath: string,
626+
): Promise<BqrsResultSetSchema[]> {
613627
const schemas = await this.cliServer.bqrsInfo(
614628
resultsPath,
615629
PAGE_SIZE.getValue(),

extensions/ql-vscode/src/run-queries-shared.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ export class QueryEvaluationInfo extends QueryOutputDir {
244244
*/
245245
async chooseResultSet(cliServer: CodeQLCliServer) {
246246
const resultSets = (
247-
await cliServer.bqrsInfo(this.resultsPaths.resultsPath, 0)
247+
await cliServer.bqrsInfo(this.resultsPaths.resultsPath)
248248
)["result-sets"];
249249
if (!resultSets.length) {
250250
return undefined;

0 commit comments

Comments
 (0)