Skip to content

Report time spent in updateGraph #35675

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions src/server/editorServices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,15 @@ namespace ts.server {

export type ProjectServiceEventHandler = (event: ProjectServiceEvent) => void;

/*@internal*/
export interface PerformanceEvent {
kind: "UpdateGraph";
durationMs: number;
}

/*@internal*/
export type PerformanceEventHandler = (event: PerformanceEvent) => void;

export interface SafeList {
[name: string]: { match: RegExp, exclude?: (string | number)[][], types?: string[] };
}
Expand Down Expand Up @@ -612,6 +621,8 @@ namespace ts.server {
/*@internal*/
readonly watchFactory: WatchFactory<WatchType, Project>;

private performanceEventHandler?: PerformanceEventHandler;

constructor(opts: ProjectServiceOptions) {
this.host = opts.host;
this.logger = opts.logger;
Expand Down Expand Up @@ -849,6 +860,13 @@ namespace ts.server {
this.eventHandler(event);
}

/* @internal */
sendUpdateGraphPerformanceEvent(durationMs: number) {
if (this.performanceEventHandler) {
this.performanceEventHandler({ kind: "UpdateGraph", durationMs });
}
}

/* @internal */
delayUpdateProjectGraphAndEnsureProjectStructureForOpenFiles(project: Project) {
this.delayUpdateProjectGraph(project);
Expand Down Expand Up @@ -2551,6 +2569,11 @@ namespace ts.server {
return info.sourceFileLike;
}

/*@internal*/
setPerformanceEventHandler(performanceEventHandler: PerformanceEventHandler) {
this.performanceEventHandler = performanceEventHandler;
}

setHostConfiguration(args: protocol.ConfigureRequestArguments) {
if (args.file) {
const info = this.getScriptInfoForNormalizedPath(toNormalizedPath(args.file));
Expand Down
1 change: 1 addition & 0 deletions src/server/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1087,6 +1087,7 @@ namespace ts.server {
removed => this.detachScriptInfoFromProject(removed)
);
const elapsed = timestamp() - start;
this.projectService.sendUpdateGraphPerformanceEvent(elapsed);
this.writeLog(`Finishing updateGraphWorker: Project: ${this.getProjectName()} Version: ${this.getProjectVersion()} structureChanged: ${hasNewProgram} Elapsed: ${elapsed}ms`);
if (this.hasAddedorRemovedFiles) {
this.print();
Expand Down
6 changes: 6 additions & 0 deletions src/server/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,12 @@ namespace ts.server.protocol {
* Contains extra information that plugin can include to be passed on
*/
metadata?: unknown;

/**
* Time spent updating the program graph, in milliseconds.
*/
/* @internal */
updateGraphDurationMs?: number;
}

/**
Expand Down
17 changes: 17 additions & 0 deletions src/server/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,8 @@ namespace ts.server {
protected projectService: ProjectService;
private changeSeq = 0;

private updateGraphDurationMs: number | undefined;

private currentRequestId!: number;
private errorCheck: MultistepOperation;

Expand Down Expand Up @@ -648,13 +650,23 @@ namespace ts.server {
syntaxOnly: opts.syntaxOnly,
};
this.projectService = new ProjectService(settings);
this.projectService.setPerformanceEventHandler(this.performanceEventHandler.bind(this));
this.gcTimer = new GcTimer(this.host, /*delay*/ 7000, this.logger);
}

private sendRequestCompletedEvent(requestId: number): void {
this.event<protocol.RequestCompletedEventBody>({ request_seq: requestId }, "requestCompleted");
}

private performanceEventHandler(event: PerformanceEvent) {
switch (event.kind) {
case "UpdateGraph": {
this.updateGraphDurationMs = (this.updateGraphDurationMs || 0) + event.durationMs;
break;
}
}
}

private defaultEventHandler(event: ProjectServiceEvent) {
switch (event.eventName) {
case ProjectsUpdatedInBackgroundEvent:
Expand Down Expand Up @@ -795,7 +807,9 @@ namespace ts.server {
command: cmdName,
request_seq: reqSeq,
success,
updateGraphDurationMs: this.updateGraphDurationMs,
};

if (success) {
let metadata: unknown;
if (isArray(info)) {
Expand Down Expand Up @@ -2549,6 +2563,9 @@ namespace ts.server {

public onMessage(message: string) {
this.gcTimer.scheduleCollect();

this.updateGraphDurationMs = undefined;

let start: number[] | undefined;
if (this.logger.hasLevel(LogLevel.requestTime)) {
start = this.hrtime();
Expand Down
15 changes: 10 additions & 5 deletions src/testRunner/unittests/tsserver/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ namespace ts.server {
seq: 0,
message: "Unrecognized JSON command: foobar",
request_seq: 0,
success: false
success: false,
updateGraphDurationMs: undefined,
};
expect(lastSent).to.deep.equal(expected);
});
Expand All @@ -126,7 +127,8 @@ namespace ts.server {
success: true,
request_seq: 0,
seq: 0,
body: undefined
body: undefined,
updateGraphDurationMs: undefined,
});
});
it("should handle literal types in request", () => {
Expand Down Expand Up @@ -323,7 +325,8 @@ namespace ts.server {
success: true,
request_seq: 0,
seq: 0,
body: undefined
body: undefined,
updateGraphDurationMs: undefined,
});
});
});
Expand Down Expand Up @@ -413,7 +416,8 @@ namespace ts.server {
type: "response",
command,
body,
success: true
success: true,
updateGraphDurationMs: undefined,
});
});
});
Expand Down Expand Up @@ -532,7 +536,8 @@ namespace ts.server {
type: "response",
command,
body,
success: true
success: true,
updateGraphDurationMs: undefined,
});
});
it("can add and respond to new protocol handlers", () => {
Expand Down
3 changes: 3 additions & 0 deletions tests/baselines/reference/api/tsserverlibrary.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9033,6 +9033,7 @@ declare namespace ts.server {
readonly syntaxOnly?: boolean;
/** Tracks projects that we have already sent telemetry for. */
private readonly seenProjects;
private performanceEventHandler?;
constructor(opts: ProjectServiceOptions);
toPath(fileName: string): Path;
private loadTypesMap;
Expand Down Expand Up @@ -9262,6 +9263,7 @@ declare namespace ts.server {
private readonly gcTimer;
protected projectService: ProjectService;
private changeSeq;
private updateGraphDurationMs;
private currentRequestId;
private errorCheck;
protected host: ServerHost;
Expand All @@ -9276,6 +9278,7 @@ declare namespace ts.server {
private readonly noGetErrOnBackgroundUpdate?;
constructor(opts: SessionOptions);
private sendRequestCompletedEvent;
private performanceEventHandler;
private defaultEventHandler;
private projectsUpdatedInBackgroundEvent;
logError(err: Error, cmd: string): void;
Expand Down