Skip to content

Commit c3efeb9

Browse files
authored
Move diagnostic duration to performance data (#59122)
1 parent 7bd7dfc commit c3efeb9

File tree

161 files changed

+5173
-2695
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

161 files changed

+5173
-2695
lines changed

src/harness/tsserverLogger.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,10 @@ export function sanitizeLog(s: string): string {
127127
s = s.replace(/"exportMapKey":\s*"\d+ \d+ /g, match => match.replace(/ \d+ /, ` * `));
128128
s = s.replace(/getIndentationAtPosition: getCurrentSourceFile: \d+(?:\.\d+)?/, `getIndentationAtPosition: getCurrentSourceFile: *`);
129129
s = s.replace(/getIndentationAtPosition: computeIndentation\s*: \d+(?:\.\d+)?/, `getIndentationAtPosition: computeIndentation: *`);
130-
s = s.replace(/"duration":\s*\d+(?:.\d+)?/g, `"duration": *`);
130+
s = s.replace(/"syntaxDiag":\s*\d+(?:.\d+)?/g, `"syntaxDiag": *`);
131+
s = s.replace(/"semanticDiag":\s*\d+(?:.\d+)?/g, `"semanticDiag": *`);
132+
s = s.replace(/"suggestionDiag":\s*\d+(?:.\d+)?/g, `"suggestionDiag": *`);
133+
s = s.replace(/"regionSemanticDiag":\s*\d+(?:.\d+)?/g, `"regionSemanticDiag": *`);
131134
s = replaceAll(s, `@ts${ts.versionMajorMinor}`, `@tsFakeMajor.Minor`);
132135
s = sanitizeHarnessLSException(s);
133136
return s;

src/server/protocol.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,22 @@ export interface PerformanceData {
311311
* The time spent creating or updating the auto-import program, in milliseconds.
312312
*/
313313
createAutoImportProviderProgramDurationMs?: number;
314+
/**
315+
* The time spent computing diagnostics, in milliseconds.
316+
*/
317+
diagnosticsDuration?: FileDiagnosticPerformanceData[];
318+
}
319+
320+
/**
321+
* Time spent computing each kind of diagnostics, in milliseconds.
322+
*/
323+
export type DiagnosticPerformanceData = { [Kind in DiagnosticEventKind]?: number; };
324+
325+
export interface FileDiagnosticPerformanceData extends DiagnosticPerformanceData {
326+
/**
327+
* The file for which the performance data is reported.
328+
*/
329+
file: string;
314330
}
315331

316332
/**
@@ -2588,11 +2604,6 @@ export interface DiagnosticEventBody {
25882604
* Spans where the region diagnostic was requested, if this is a region semantic diagnostic event.
25892605
*/
25902606
spans?: TextSpan[];
2591-
2592-
/**
2593-
* Time spent computing the diagnostics, in milliseconds.
2594-
*/
2595-
duration?: number;
25962607
}
25972608

25982609
export type DiagnosticEventKind = "semanticDiag" | "syntaxDiag" | "suggestionDiag" | "regionSemanticDiag";

src/server/session.ts

Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -338,16 +338,21 @@ interface NextStep {
338338
delay(actionType: string, ms: number, action: () => void): void;
339339
}
340340

341+
/** @internal */
342+
export type PerformanceData =
343+
& Omit<protocol.PerformanceData, "diagnosticsDuration">
344+
& { diagnosticsDuration?: Map<NormalizedPath, protocol.DiagnosticPerformanceData>; };
345+
341346
/**
342347
* External capabilities used by multistep operation
343348
*/
344349
interface MultistepOperationHost {
345350
getCurrentRequestId(): number;
346-
getPerformanceData(): protocol.PerformanceData | undefined;
347-
sendRequestCompletedEvent(requestId: number, performanceData: protocol.PerformanceData | undefined): void;
351+
getPerformanceData(): PerformanceData | undefined;
352+
sendRequestCompletedEvent(requestId: number, performanceData: PerformanceData | undefined): void;
348353
getServerHost(): ServerHost;
349354
isCancellationRequested(): boolean;
350-
executeWithRequestId(requestId: number, action: () => void, performanceData: protocol.PerformanceData | undefined): void;
355+
executeWithRequestId(requestId: number, action: () => void, performanceData: PerformanceData | undefined): void;
351356
logError(error: Error, message: string): void;
352357
}
353358

@@ -357,7 +362,7 @@ interface MultistepOperationHost {
357362
*/
358363
class MultistepOperation implements NextStep {
359364
private requestId: number | undefined;
360-
private performanceData: protocol.PerformanceData | undefined;
365+
private performanceData: PerformanceData | undefined;
361366
private timerHandle: any;
362367
private immediateId: number | undefined;
363368

@@ -980,7 +985,7 @@ export class Session<TMessage = string> implements EventSender {
980985
protected projectService: ProjectService;
981986
private changeSeq = 0;
982987

983-
private performanceData: protocol.PerformanceData | undefined;
988+
private performanceData: PerformanceData | undefined;
984989

985990
private currentRequestId!: number;
986991
private errorCheck: MultistepOperation;
@@ -1073,17 +1078,36 @@ export class Session<TMessage = string> implements EventSender {
10731078
}
10741079
}
10751080

1076-
private sendRequestCompletedEvent(requestId: number, performanceData: protocol.PerformanceData | undefined): void {
1077-
this.event<protocol.RequestCompletedEventBody>({ request_seq: requestId, performanceData }, "requestCompleted");
1081+
private sendRequestCompletedEvent(requestId: number, performanceData: PerformanceData | undefined): void {
1082+
this.event<protocol.RequestCompletedEventBody>(
1083+
{
1084+
request_seq: requestId,
1085+
performanceData: performanceData && toProtocolPerformanceData(performanceData),
1086+
},
1087+
"requestCompleted",
1088+
);
10781089
}
10791090

1080-
private addPerformanceData(key: keyof protocol.PerformanceData, value: number) {
1091+
private addPerformanceData(key: Exclude<keyof PerformanceData, "diagnosticsDuration">, value: number) {
10811092
if (!this.performanceData) {
10821093
this.performanceData = {};
10831094
}
10841095
this.performanceData[key] = (this.performanceData[key] ?? 0) + value;
10851096
}
10861097

1098+
private addDiagnosticsPerformanceData(
1099+
file: NormalizedPath,
1100+
kind: protocol.DiagnosticEventKind,
1101+
duration: number,
1102+
): void {
1103+
if (!this.performanceData) {
1104+
this.performanceData = {};
1105+
}
1106+
let fileDiagnosticDuration = this.performanceData.diagnosticsDuration?.get(file);
1107+
if (!fileDiagnosticDuration) (this.performanceData.diagnosticsDuration ??= new Map()).set(file, fileDiagnosticDuration = {});
1108+
fileDiagnosticDuration[kind] = duration;
1109+
}
1110+
10871111
private performanceEventHandler(event: PerformanceEvent) {
10881112
switch (event.kind) {
10891113
case "UpdateGraph":
@@ -1228,7 +1252,7 @@ export class Session<TMessage = string> implements EventSender {
12281252
cmdName: string,
12291253
reqSeq: number,
12301254
success: boolean,
1231-
performanceData: protocol.PerformanceData | undefined,
1255+
performanceData: PerformanceData | undefined,
12321256
message?: string,
12331257
): void {
12341258
const res: protocol.Response = {
@@ -1237,7 +1261,7 @@ export class Session<TMessage = string> implements EventSender {
12371261
command: cmdName,
12381262
request_seq: reqSeq,
12391263
success,
1240-
performanceData,
1264+
performanceData: performanceData && toProtocolPerformanceData(performanceData),
12411265
};
12421266

12431267
if (success) {
@@ -1331,12 +1355,12 @@ export class Session<TMessage = string> implements EventSender {
13311355
file,
13321356
diagnostics: diagnostics.map(diag => formatDiag(file, project, diag)),
13331357
spans: spans?.map(span => toProtocolTextSpan(span, scriptInfo)),
1334-
duration,
13351358
};
13361359
this.event<protocol.DiagnosticEventBody>(
13371360
body,
13381361
kind,
13391362
);
1363+
this.addDiagnosticsPerformanceData(file, kind, duration);
13401364
}
13411365
catch (err) {
13421366
this.logError(err, kind);
@@ -3737,8 +3761,8 @@ export class Session<TMessage = string> implements EventSender {
37373761

37383762
public executeWithRequestId<T>(requestId: number, f: () => T): T;
37393763
/** @internal */
3740-
public executeWithRequestId<T>(requestId: number, f: () => T, perfomanceData: protocol.PerformanceData | undefined): T; // eslint-disable-line @typescript-eslint/unified-signatures
3741-
public executeWithRequestId<T>(requestId: number, f: () => T, perfomanceData?: protocol.PerformanceData) {
3764+
public executeWithRequestId<T>(requestId: number, f: () => T, perfomanceData: PerformanceData | undefined): T; // eslint-disable-line @typescript-eslint/unified-signatures
3765+
public executeWithRequestId<T>(requestId: number, f: () => T, perfomanceData?: PerformanceData) {
37423766
const currentPerformanceData = this.performanceData;
37433767
try {
37443768
this.performanceData = perfomanceData;
@@ -3878,6 +3902,12 @@ interface FileAndProject {
38783902
readonly project: Project;
38793903
}
38803904

3905+
function toProtocolPerformanceData(performanceData: PerformanceData): protocol.PerformanceData {
3906+
const diagnosticsDuration = performanceData.diagnosticsDuration &&
3907+
arrayFrom(performanceData.diagnosticsDuration, ([file, data]) => ({ ...data, file }));
3908+
return { ...performanceData, diagnosticsDuration };
3909+
}
3910+
38813911
function toProtocolTextSpan(textSpan: TextSpan, scriptInfo: ScriptInfo): protocol.TextSpan {
38823912
return {
38833913
start: scriptInfo.positionToLineOffset(textSpan.start),
@@ -3928,7 +3958,7 @@ function convertNewFileTextChangeToCodeEdit(textChanges: FileTextChanges): proto
39283958
export interface HandlerResponse {
39293959
response?: {};
39303960
responseRequired?: boolean;
3931-
/** @internal */ performanceData?: protocol.PerformanceData;
3961+
/** @internal */ performanceData?: PerformanceData;
39323962
}
39333963

39343964
/** @internal */

tests/baselines/reference/api/typescript.d.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,22 @@ declare namespace ts {
214214
* The time spent creating or updating the auto-import program, in milliseconds.
215215
*/
216216
createAutoImportProviderProgramDurationMs?: number;
217+
/**
218+
* The time spent computing diagnostics, in milliseconds.
219+
*/
220+
diagnosticsDuration?: FileDiagnosticPerformanceData[];
221+
}
222+
/**
223+
* Time spent computing each kind of diagnostics, in milliseconds.
224+
*/
225+
export type DiagnosticPerformanceData = {
226+
[Kind in DiagnosticEventKind]?: number;
227+
};
228+
export interface FileDiagnosticPerformanceData extends DiagnosticPerformanceData {
229+
/**
230+
* The file for which the performance data is reported.
231+
*/
232+
file: string;
217233
}
218234
/**
219235
* Arguments for FileRequest messages.
@@ -1979,10 +1995,6 @@ declare namespace ts {
19791995
* Spans where the region diagnostic was requested, if this is a region semantic diagnostic event.
19801996
*/
19811997
spans?: TextSpan[];
1982-
/**
1983-
* Time spent computing the diagnostics, in milliseconds.
1984-
*/
1985-
duration?: number;
19861998
}
19871999
export type DiagnosticEventKind = "semanticDiag" | "syntaxDiag" | "suggestionDiag" | "regionSemanticDiag";
19882000
/**
@@ -3416,6 +3428,7 @@ declare namespace ts {
34163428
constructor(opts: SessionOptions);
34173429
private sendRequestCompletedEvent;
34183430
private addPerformanceData;
3431+
private addDiagnosticsPerformanceData;
34193432
private performanceEventHandler;
34203433
private defaultEventHandler;
34213434
private projectsUpdatedInBackgroundEvent;

tests/baselines/reference/tsserver/cancellationT/Geterr-is-cancellable.js

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -338,8 +338,7 @@ Info seq [hh:mm:ss:mss] event:
338338
"event": "syntaxDiag",
339339
"body": {
340340
"file": "/a/app.ts",
341-
"diagnostics": [],
342-
"duration": *
341+
"diagnostics": []
343342
}
344343
}
345344
TestServerCancellationToken:: resetRequest:: 5 is as expected
@@ -360,7 +359,15 @@ Info seq [hh:mm:ss:mss] event:
360359
"type": "event",
361360
"event": "requestCompleted",
362361
"body": {
363-
"request_seq": 5
362+
"request_seq": 5,
363+
"performanceData": {
364+
"diagnosticsDuration": [
365+
{
366+
"syntaxDiag": *,
367+
"file": "/a/app.ts"
368+
}
369+
]
370+
}
364371
}
365372
}
366373
TestServerCancellationToken:: resetRequest:: 5 is as expected
@@ -398,8 +405,7 @@ Info seq [hh:mm:ss:mss] event:
398405
"event": "syntaxDiag",
399406
"body": {
400407
"file": "/a/app.ts",
401-
"diagnostics": [],
402-
"duration": *
408+
"diagnostics": []
403409
}
404410
}
405411
TestServerCancellationToken:: resetRequest:: 6 is as expected
@@ -419,8 +425,7 @@ Info seq [hh:mm:ss:mss] event:
419425
"event": "semanticDiag",
420426
"body": {
421427
"file": "/a/app.ts",
422-
"diagnostics": [],
423-
"duration": *
428+
"diagnostics": []
424429
}
425430
}
426431
TestServerCancellationToken:: resetRequest:: 6 is as expected
@@ -440,8 +445,7 @@ Info seq [hh:mm:ss:mss] event:
440445
"event": "suggestionDiag",
441446
"body": {
442447
"file": "/a/app.ts",
443-
"diagnostics": [],
444-
"duration": *
448+
"diagnostics": []
445449
}
446450
}
447451
Info seq [hh:mm:ss:mss] event:
@@ -450,7 +454,17 @@ Info seq [hh:mm:ss:mss] event:
450454
"type": "event",
451455
"event": "requestCompleted",
452456
"body": {
453-
"request_seq": 6
457+
"request_seq": 6,
458+
"performanceData": {
459+
"diagnosticsDuration": [
460+
{
461+
"syntaxDiag": *,
462+
"semanticDiag": *,
463+
"suggestionDiag": *,
464+
"file": "/a/app.ts"
465+
}
466+
]
467+
}
454468
}
455469
}
456470
TestServerCancellationToken:: resetRequest:: 6 is as expected
@@ -488,8 +502,7 @@ Info seq [hh:mm:ss:mss] event:
488502
"event": "syntaxDiag",
489503
"body": {
490504
"file": "/a/app.ts",
491-
"diagnostics": [],
492-
"duration": *
505+
"diagnostics": []
493506
}
494507
}
495508
TestServerCancellationToken:: resetRequest:: 7 is as expected
@@ -519,7 +532,15 @@ Info seq [hh:mm:ss:mss] event:
519532
"type": "event",
520533
"event": "requestCompleted",
521534
"body": {
522-
"request_seq": 7
535+
"request_seq": 7,
536+
"performanceData": {
537+
"diagnosticsDuration": [
538+
{
539+
"syntaxDiag": *,
540+
"file": "/a/app.ts"
541+
}
542+
]
543+
}
523544
}
524545
}
525546
TestServerCancellationToken:: resetRequest:: 8 is as expected

tests/baselines/reference/tsserver/cancellationT/is-attached-to-request.js

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,7 @@ Info seq [hh:mm:ss:mss] event:
146146
"event": "syntaxDiag",
147147
"body": {
148148
"file": "/a/b/app.ts",
149-
"diagnostics": [],
150-
"duration": *
149+
"diagnostics": []
151150
}
152151
}
153152
TestServerCancellationToken:: resetRequest:: 2 is as expected
@@ -167,8 +166,7 @@ Info seq [hh:mm:ss:mss] event:
167166
"event": "semanticDiag",
168167
"body": {
169168
"file": "/a/b/app.ts",
170-
"diagnostics": [],
171-
"duration": *
169+
"diagnostics": []
172170
}
173171
}
174172
TestServerCancellationToken:: resetRequest:: 2 is as expected
@@ -188,8 +186,7 @@ Info seq [hh:mm:ss:mss] event:
188186
"event": "suggestionDiag",
189187
"body": {
190188
"file": "/a/b/app.ts",
191-
"diagnostics": [],
192-
"duration": *
189+
"diagnostics": []
193190
}
194191
}
195192
Info seq [hh:mm:ss:mss] event:
@@ -198,7 +195,17 @@ Info seq [hh:mm:ss:mss] event:
198195
"type": "event",
199196
"event": "requestCompleted",
200197
"body": {
201-
"request_seq": 2
198+
"request_seq": 2,
199+
"performanceData": {
200+
"diagnosticsDuration": [
201+
{
202+
"syntaxDiag": *,
203+
"semanticDiag": *,
204+
"suggestionDiag": *,
205+
"file": "/a/b/app.ts"
206+
}
207+
]
208+
}
202209
}
203210
}
204211
TestServerCancellationToken:: resetRequest:: 2 is as expected

0 commit comments

Comments
 (0)