From 1982f52573e6bc10ad7d49992ced7a0ae4235064 Mon Sep 17 00:00:00 2001 From: Alexander Eyers-Taylor Date: Mon, 9 Dec 2024 23:51:31 +0000 Subject: [PATCH 1/4] Add cache of query schemas to results view --- .../contextual/cached-operation.ts | 16 +++++++++++++++- .../ql-vscode/src/local-queries/results-view.ts | 14 ++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/extensions/ql-vscode/src/language-support/contextual/cached-operation.ts b/extensions/ql-vscode/src/language-support/contextual/cached-operation.ts index a50e7d03b01..3c6e845d740 100644 --- a/extensions/ql-vscode/src/language-support/contextual/cached-operation.ts +++ b/extensions/ql-vscode/src/language-support/contextual/cached-operation.ts @@ -7,6 +7,7 @@ export class CachedOperation { private readonly operation: (t: string, ...args: S) => Promise; private readonly cached: Map; private readonly lru: string[]; + private generation: number; private readonly inProgressCallbacks: Map< string, Array<[(u: U) => void, (reason?: Error) => void]> @@ -17,6 +18,7 @@ export class CachedOperation { private cacheSize = 100, ) { this.operation = operation; + this.generation = 0; this.lru = []; this.inProgressCallbacks = new Map< string, @@ -46,7 +48,7 @@ export class CachedOperation { inProgressCallback.push([resolve, reject]); }); } - + const origGeneration = this.generation; // Otherwise compute the new value, but leave a callback to allow sharing work const callbacks: Array<[(u: U) => void, (reason?: Error) => void]> = []; this.inProgressCallbacks.set(t, callbacks); @@ -54,6 +56,11 @@ export class CachedOperation { const result = await this.operation(t, ...args); callbacks.forEach((f) => f[0](result)); this.inProgressCallbacks.delete(t); + if (this.generation !== origGeneration) { + // Cache was reset in the meantime so don't trust this + // result enough to cache it. + return result; + } if (this.lru.length > this.cacheSize) { const toRemove = this.lru.shift()!; this.cached.delete(toRemove); @@ -69,4 +76,11 @@ export class CachedOperation { this.inProgressCallbacks.delete(t); } } + + reset() { + this.cached.clear(); + this.lru.length = 0; + this.generation++; + this.inProgressCallbacks.clear(); + } } diff --git a/extensions/ql-vscode/src/local-queries/results-view.ts b/extensions/ql-vscode/src/local-queries/results-view.ts index 18ee93f8543..4e28e9f9c73 100644 --- a/extensions/ql-vscode/src/local-queries/results-view.ts +++ b/extensions/ql-vscode/src/local-queries/results-view.ts @@ -75,6 +75,7 @@ import type { App } from "../common/app"; import type { Disposable } from "../common/disposable-object"; import type { RawResultSet } from "../common/raw-result-types"; import type { BqrsResultSetSchema } from "../common/bqrs-cli-types"; +import { CachedOperation } from "../language-support/contextual/cached-operation"; /** * results-view.ts @@ -177,6 +178,8 @@ export class ResultsView extends AbstractWebview< // Event listeners that should be disposed of when the view is disposed. private disposableEventListeners: Disposable[] = []; + private schemaCache: CachedOperation<[], BqrsResultSetSchema[]>; + constructor( app: App, private databaseManager: DatabaseManager, @@ -206,6 +209,10 @@ export class ResultsView extends AbstractWebview< } }), ); + + this.schemaCache = new CachedOperation( + this.getResultSetSchemasImpl.bind(this), + ); } public getCommands(): ResultsViewCommands { @@ -420,6 +427,7 @@ export class ResultsView extends AbstractWebview< ); return; } + this.schemaCache.reset(); // Notify the webview that it should expect new results. await this.postMessage({ t: "resultsUpdating" }); await this._displayedQuery.completedQuery.updateSortState( @@ -610,6 +618,12 @@ export class ResultsView extends AbstractWebview< selectedTable = "", ): Promise { const resultsPath = completedQuery.getResultsPath(selectedTable); + return this.schemaCache.get(resultsPath); + } + + private async getResultSetSchemasImpl( + resultsPath: string, + ): Promise { const schemas = await this.cliServer.bqrsInfo( resultsPath, PAGE_SIZE.getValue(), From f0170e21431bd96f155ca3cb4a1510b0f4af1b7e Mon Sep 17 00:00:00 2001 From: Alexander Eyers-Taylor Date: Tue, 10 Dec 2024 12:27:21 +0000 Subject: [PATCH 2/4] Update changelog --- extensions/ql-vscode/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/extensions/ql-vscode/CHANGELOG.md b/extensions/ql-vscode/CHANGELOG.md index 5e1c5ac390f..a28bbf9e12c 100644 --- a/extensions/ql-vscode/CHANGELOG.md +++ b/extensions/ql-vscode/CHANGELOG.md @@ -4,6 +4,7 @@ - Add a palette command that allows importing all databases directly inside of a parent folder. [#3797](https://github.com/github/vscode-codeql/pull/3797) - Only use VS Code telemetry settings instead of using `codeQL.telemetry.enableTelemetry` [#3853](https://github.com/github/vscode-codeql/pull/3853) +- Improve the performance of the results view with large numbers of results. ## 1.16.1 - 6 November 2024 From ab35550816cf7a1058c02e18aee904a25a4061fd Mon Sep 17 00:00:00 2001 From: Alexander Eyers-Taylor Date: Tue, 10 Dec 2024 12:29:26 +0000 Subject: [PATCH 3/4] Don't call bqrsInfo with a page size of 0 --- extensions/ql-vscode/src/run-queries-shared.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/ql-vscode/src/run-queries-shared.ts b/extensions/ql-vscode/src/run-queries-shared.ts index 6dbaa8e651b..dac447ee20b 100644 --- a/extensions/ql-vscode/src/run-queries-shared.ts +++ b/extensions/ql-vscode/src/run-queries-shared.ts @@ -244,7 +244,7 @@ export class QueryEvaluationInfo extends QueryOutputDir { */ async chooseResultSet(cliServer: CodeQLCliServer) { const resultSets = ( - await cliServer.bqrsInfo(this.resultsPaths.resultsPath, 0) + await cliServer.bqrsInfo(this.resultsPaths.resultsPath) )["result-sets"]; if (!resultSets.length) { return undefined; From c2e7255182ebc1be170ddc6d1e1c3aec9d0d6f7b Mon Sep 17 00:00:00 2001 From: Alexander Eyers-Taylor Date: Fri, 13 Dec 2024 16:49:34 +0000 Subject: [PATCH 4/4] Update extensions/ql-vscode/CHANGELOG.md Co-authored-by: Andrew Eisenberg --- extensions/ql-vscode/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/ql-vscode/CHANGELOG.md b/extensions/ql-vscode/CHANGELOG.md index a28bbf9e12c..53dba290fc4 100644 --- a/extensions/ql-vscode/CHANGELOG.md +++ b/extensions/ql-vscode/CHANGELOG.md @@ -4,7 +4,7 @@ - Add a palette command that allows importing all databases directly inside of a parent folder. [#3797](https://github.com/github/vscode-codeql/pull/3797) - Only use VS Code telemetry settings instead of using `codeQL.telemetry.enableTelemetry` [#3853](https://github.com/github/vscode-codeql/pull/3853) -- Improve the performance of the results view with large numbers of results. +- Improve the performance of the results view with large numbers of results. [#3862](https://github.com/github/vscode-codeql/pull/3862) ## 1.16.1 - 6 November 2024