Skip to content

Commit 476dcb2

Browse files
committed
perf: yield after checking diagnostics for an open file
This commit contains a few perf improvements: 1. Increase debounce time from 200ms to 300ms This increases the likelihood of consolidating diagnostics requests, but should have little impact on user perception. 2. While in the middle of a diagnositc check, stop the operation if there is another pending diagnostic request. 3. After checking a file, yield the execution thread so that the server gets a chance to process incoming requests.
1 parent 869d09d commit 476dcb2

File tree

2 files changed

+28
-4
lines changed

2 files changed

+28
-4
lines changed

server/src/session.ts

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import {isNgLanguageService, NgLanguageService, PluginConfig} from '@angular/language-service/api';
1010
import * as assert from 'assert';
1111
import * as ts from 'typescript/lib/tsserverlibrary';
12+
import {promisify} from 'util';
1213
import * as lsp from 'vscode-languageserver/node';
1314

1415
import {ServerOptions} from '../common/initialize';
@@ -20,7 +21,7 @@ import {readNgCompletionData, tsCompletionEntryToLspCompletionItem} from './comp
2021
import {tsDiagnosticToLspDiagnostic} from './diagnostic';
2122
import {resolveAndRunNgcc} from './ngcc';
2223
import {ServerHost} from './server_host';
23-
import {filePathToUri, isConfiguredProject, lspPositionToTsPosition, lspRangeToTsPositions, tsTextSpanToLspRange, uriToFilePath} from './utils';
24+
import {filePathToUri, isConfiguredProject, isDebugMode, lspPositionToTsPosition, lspRangeToTsPositions, tsTextSpanToLspRange, uriToFilePath} from './utils';
2425
import {resolve, Version} from './version_provider';
2526

2627
export interface SessionOptions {
@@ -39,6 +40,7 @@ enum LanguageId {
3940

4041
// Empty definition range for files without `scriptInfo`
4142
const EMPTY_RANGE = lsp.Range.create(0, 0, 0, 0);
43+
const setImmediateP = promisify(setImmediate);
4244

4345
/**
4446
* Session is a wrapper around lsp.IConnection, with all the necessary protocol
@@ -293,7 +295,7 @@ export class Session {
293295
* @param openFiles
294296
* @param delay time to wait before sending request (milliseconds)
295297
*/
296-
private triggerDiagnostics(openFiles: string[], delay: number = 200) {
298+
private triggerDiagnostics(openFiles: string[], delay: number = 300) {
297299
// Do not immediately send a diagnostics request. Send only after user has
298300
// stopped typing after the specified delay.
299301
if (this.diagnosticsTimeout) {
@@ -313,19 +315,39 @@ export class Session {
313315
* Execute diagnostics request for each of the specified `openFiles`.
314316
* @param openFiles
315317
*/
316-
private sendPendingDiagnostics(openFiles: string[]) {
317-
for (const fileName of openFiles) {
318+
private async sendPendingDiagnostics(openFiles: string[]) {
319+
for (let i = 0; i < openFiles.length; ++i) {
320+
const fileName = openFiles[i];
318321
const result = this.getLSAndScriptInfo(fileName);
319322
if (!result) {
320323
continue;
321324
}
325+
const label = `getSemanticDiagnostics - ${fileName}`;
326+
if (isDebugMode) {
327+
console.time(label);
328+
}
322329
const diagnostics = result.languageService.getSemanticDiagnostics(fileName);
330+
if (isDebugMode) {
331+
console.timeEnd(label);
332+
}
323333
// Need to send diagnostics even if it's empty otherwise editor state will
324334
// not be updated.
325335
this.connection.sendDiagnostics({
326336
uri: filePathToUri(fileName),
327337
diagnostics: diagnostics.map(d => tsDiagnosticToLspDiagnostic(d, result.scriptInfo)),
328338
});
339+
if (this.diagnosticsTimeout) {
340+
// There is a pending request to check diagnostics for all open files,
341+
// so stop this one immediately.
342+
return;
343+
}
344+
if (i < openFiles.length - 1) {
345+
// If this is not the last file, yield so that pending I/O events get a
346+
// chance to run. This will open an opportunity for the server to process
347+
// incoming requests. The next file will be checked in the next iteration
348+
// of the event loop.
349+
await setImmediateP();
350+
}
329351
}
330352
}
331353

server/src/utils.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import * as ts from 'typescript/lib/tsserverlibrary';
1010
import * as lsp from 'vscode-languageserver';
1111
import {URI} from 'vscode-uri';
1212

13+
export const isDebugMode = process.env['NG_DEBUG'] === 'true';
14+
1315
enum Scheme {
1416
File = 'file',
1517
}

0 commit comments

Comments
 (0)