From 116000e5480703f5de7f0354a6cc03d8a1db8945 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Wed, 11 Nov 2020 12:58:00 -0800 Subject: [PATCH 1/2] Fold tracing.begin and end into push and pop Storing the arguments on the stack will make it possible to forego try-finally blocks when we start tracing in server scenarios, which have to handle cancellation. --- src/compiler/binder.ts | 5 ++--- src/compiler/checker.ts | 5 ++--- src/compiler/parser.ts | 5 ++--- src/compiler/program.ts | 15 ++++++-------- src/compiler/tracing.ts | 44 ++++++++++++++++++++--------------------- 5 files changed, 33 insertions(+), 41 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 8929ec075f9..3c51e9e6050 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -174,15 +174,14 @@ namespace ts { const binder = createBinder(); export function bindSourceFile(file: SourceFile, options: CompilerOptions) { - const tracingData: tracing.EventData = [tracing.Phase.Bind, "bindSourceFile", { path: file.path }]; - tracing.begin(...tracingData); + tracing.push(tracing.Phase.Bind, "bindSourceFile", { path: file.path }, /*separateBeginAndEnd*/ true); performance.mark("beforeBind"); perfLogger.logStartBindFile("" + file.fileName); binder(file, options); perfLogger.logStopBindFile(); performance.mark("afterBind"); performance.measure("Bind", "beforeBind", "afterBind"); - tracing.end(...tracingData); + tracing.pop(); } function createBinder(): (file: SourceFile, options: CompilerOptions) => void { diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 74a48de2be4..04d2bd912bc 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -36987,13 +36987,12 @@ namespace ts { } function checkSourceFile(node: SourceFile) { - const tracingData: tracing.EventData = [tracing.Phase.Check, "checkSourceFile", { path: node.path }]; - tracing.begin(...tracingData); + tracing.push(tracing.Phase.Check, "checkSourceFile", { path: node.path }, /*separateBeginAndEnd*/ true); performance.mark("beforeCheck"); checkSourceFileWorker(node); performance.mark("afterCheck"); performance.measure("Check", "beforeCheck", "afterCheck"); - tracing.end(...tracingData); + tracing.pop(); } function unusedIsError(kind: UnusedKind, isAmbient: boolean): boolean { diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 317832ac2ee..c86909be174 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -614,8 +614,7 @@ namespace ts { } export function createSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, setParentNodes = false, scriptKind?: ScriptKind): SourceFile { - const tracingData: tracing.EventData = [tracing.Phase.Parse, "createSourceFile", { path: fileName }]; - tracing.begin(...tracingData); + tracing.push(tracing.Phase.Parse, "createSourceFile", { path: fileName }, /*separateBeginAndEnd*/ true); performance.mark("beforeParse"); let result: SourceFile; @@ -630,7 +629,7 @@ namespace ts { performance.mark("afterParse"); performance.measure("Parse", "beforeParse", "afterParse"); - tracing.end(...tracingData); + tracing.pop(); return result; } diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 16d6a6bd367..33c3b67e9ed 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -780,8 +780,7 @@ namespace ts { // Track source files that are source files found by searching under node_modules, as these shouldn't be compiled. const sourceFilesFoundSearchingNodeModules = new Map(); - const tracingData: tracing.EventData = [tracing.Phase.Program, "createProgram"]; - tracing.begin(...tracingData); + tracing.push(tracing.Phase.Program, "createProgram", {}, /*separateBeginAndEnd*/ true); performance.mark("beforeProgram"); const host = createProgramOptions.host || createCompilerHost(options); @@ -1041,7 +1040,7 @@ namespace ts { verifyCompilerOptions(); performance.mark("afterProgram"); performance.measure("Program", "beforeProgram", "afterProgram"); - tracing.end(...tracingData); + tracing.pop(); return program; @@ -1603,8 +1602,7 @@ namespace ts { function emitBuildInfo(writeFileCallback?: WriteFileCallback): EmitResult { Debug.assert(!outFile(options)); - const tracingData: tracing.EventData = [tracing.Phase.Emit, "emitBuildInfo"]; - tracing.begin(...tracingData); + tracing.push(tracing.Phase.Emit, "emitBuildInfo", {}, /*separateBeginAndEnd*/ true); performance.mark("beforeEmit"); const emitResult = emitFiles( notImplementedResolver, @@ -1617,7 +1615,7 @@ namespace ts { performance.mark("afterEmit"); performance.measure("Emit", "beforeEmit", "afterEmit"); - tracing.end(...tracingData); + tracing.pop(); return emitResult; } @@ -1678,10 +1676,9 @@ namespace ts { } function emit(sourceFile?: SourceFile, writeFileCallback?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, transformers?: CustomTransformers, forceDtsEmit?: boolean): EmitResult { - const tracingData: tracing.EventData = [tracing.Phase.Emit, "emit", { path: sourceFile?.path }]; - tracing.begin(...tracingData); + tracing.push(tracing.Phase.Emit, "emit", { path: sourceFile?.path }, /*separateBeginAndEnd*/ true); const result = runWithCancellationToken(() => emitWorker(program, sourceFile, writeFileCallback, cancellationToken, emitOnlyDtsFiles, transformers, forceDtsEmit)); - tracing.end(...tracingData); + tracing.pop(); return result; } diff --git a/src/compiler/tracing.ts b/src/compiler/tracing.ts index f00207ae198..6b666fa1514 100644 --- a/src/compiler/tracing.ts +++ b/src/compiler/tracing.ts @@ -92,40 +92,38 @@ namespace ts.tracing { Emit = "emit", } - export type EventData = [phase: Phase, name: string, args?: object]; - - /** Note: `push`/`pop` should be used by default. - * `begin`/`end` are for special cases where we need the data point even if the event never - * terminates (typically for reducing a scenario too big to trace to one that can be completed). - * In the future we might implement an exit handler to dump unfinished events which would - * deprecate these operations. - */ - export function begin(phase: Phase, name: string, args?: object) { - if (!traceFd) return; - writeEvent("B", phase, name, args); - } - export function end(phase: Phase, name: string, args?: object) { - if (!traceFd) return; - writeEvent("E", phase, name, args); - } - export function instant(phase: Phase, name: string, args?: object) { if (!traceFd) return; writeEvent("I", phase, name, args, `"s":"g"`); } // Used for "Complete" (ph:"X") events - const completeEvents: { phase: Phase, name: string, args?: object, time: number }[] = []; - export function push(phase: Phase, name: string, args?: object) { + const completeEvents: { phase: Phase, name: string, args?: object, time: number, separateBeginAndEnd: boolean }[] = []; + + /** + * @param separateBeginAndEnd - used for special cases where we need the trace point even if the event + * never terminates (typically for reducing a scenario too big to trace to one that can be completed). + * In the future we might implement an exit handler to dump unfinished events which would deprecate + * these operations. + */ + export function push(phase: Phase, name: string, args?: object, separateBeginAndEnd: boolean = false) { if (!traceFd) return; - completeEvents.push({ phase, name, args, time: 1000 * timestamp() }); + if (separateBeginAndEnd) { + writeEvent("B", phase, name, args); + } + completeEvents.push({ phase, name, args, time: 1000 * timestamp(), separateBeginAndEnd }); } export function pop() { if (!traceFd) return; Debug.assert(completeEvents.length > 0); - const { phase, name, args, time } = completeEvents.pop()!; - const dur = 1000 * timestamp() - time; - writeEvent("X", phase, name, args, `"dur":${dur}`, time); + const { phase, name, args, time, separateBeginAndEnd } = completeEvents.pop()!; + if (separateBeginAndEnd) { + writeEvent("E", phase, name, args); + } + else { + const dur = 1000 * timestamp() - time; + writeEvent("X", phase, name, args, `"dur":${dur}`, time); + } } function writeEvent(eventType: string, phase: Phase, name: string, args: object | undefined, extras?: string, From e8996a34a93f67953f1cdacfd9e8f1e83338da96 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Wed, 11 Nov 2020 13:56:27 -0800 Subject: [PATCH 2/2] Remove redundant type annotation --- src/compiler/tracing.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/tracing.ts b/src/compiler/tracing.ts index 6b666fa1514..95deeb1b33c 100644 --- a/src/compiler/tracing.ts +++ b/src/compiler/tracing.ts @@ -106,7 +106,7 @@ namespace ts.tracing { * In the future we might implement an exit handler to dump unfinished events which would deprecate * these operations. */ - export function push(phase: Phase, name: string, args?: object, separateBeginAndEnd: boolean = false) { + export function push(phase: Phase, name: string, args?: object, separateBeginAndEnd = false) { if (!traceFd) return; if (separateBeginAndEnd) { writeEvent("B", phase, name, args);