Skip to content

Commit 56f546b

Browse files
committed
Emit read write times
1 parent 3113f62 commit 56f546b

File tree

7 files changed

+92
-40
lines changed

7 files changed

+92
-40
lines changed

src/compiler/builder.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -813,17 +813,24 @@ namespace ts {
813813
return !!outFile(info.options || {});
814814
}
815815

816+
function getProgramBuildInfo(state: BuilderProgramState, getCanonicalFileName: GetCanonicalFileName) {
817+
if (outFile(state.compilerOptions) && !state.compilerOptions.composite) return;
818+
performance.mark("beforeGetProgramBuildInfo");
819+
const result = getProgramBuildInfoWorker(state, getCanonicalFileName);
820+
performance.mark("afterGetProgramBuildInfo");
821+
performance.measure("BuildInfo generation", "beforeGetProgramBuildInfo", "afterGetProgramBuildInfo");
822+
return result;
823+
}
824+
816825
/**
817826
* Gets the program information to be emitted in buildInfo so that we can use it to create new program
818827
*/
819-
function getProgramBuildInfo(state: BuilderProgramState, getCanonicalFileName: GetCanonicalFileName): ProgramBuildInfo | undefined {
820-
const outFilePath = outFile(state.compilerOptions);
821-
if (outFilePath && !state.compilerOptions.composite) return;
828+
function getProgramBuildInfoWorker(state: BuilderProgramState, getCanonicalFileName: GetCanonicalFileName): ProgramBuildInfo | undefined {
822829
const currentDirectory = Debug.checkDefined(state.program).getCurrentDirectory();
823830
const buildInfoDirectory = getDirectoryPath(getNormalizedAbsolutePath(getTsBuildInfoEmitOutputFilePath(state.compilerOptions)!, currentDirectory));
824831
// Convert the file name to Path here if we set the fileName instead to optimize multiple d.ts file emits and having to compute Canonical path
825832
const latestChangedDtsFile = state.latestChangedDtsFile ? relativeToBuildInfoEnsuringAbsolutePath(state.latestChangedDtsFile) : undefined;
826-
if (outFilePath) {
833+
if (outFile(state.compilerOptions)) {
827834
const fileNames: string[] = [];
828835
const fileInfos: string[] = [];
829836
state.program!.getRootFileNames().forEach(f => {

src/compiler/emitter.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,10 @@ namespace ts {
365365
}
366366
const version = ts.version; // Extracted into a const so the form is stable between namespace and module
367367
const buildInfo: BuildInfo = { bundle, program, version };
368+
performance.mark("beforeBuildInfoStringify");
368369
const buildInfoText = getBuildInfoText(buildInfo);
370+
performance.mark("afterBuildInfoStringify");
371+
performance.measure("BuildInfo stringify", "beforeBuildInfoStringify", "afterBuildInfoStringify");
369372
host.buildInfoCallbacks?.onWrite(buildInfoText.length);
370373
// Pass buildinfo as additional data to avoid having to reparse
371374
writeFile(host, emitterDiagnostics, buildInfoPath, buildInfoText, /*writeByteOrderMark*/ false, /*sourceFiles*/ undefined, { buildInfo });

src/compiler/factory/nodeFactory.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6750,9 +6750,11 @@ namespace ts {
67506750
buildInfo = host.getBuildInfo(declarationMapTextOrBuildInfoPath, options) ?? false;
67516751
}
67526752
else {
6753+
host?.buildInfoCallbacks?.onReadStart(options);
67536754
const result = textGetter(declarationMapTextOrBuildInfoPath);
6754-
if (result) host?.buildInfoCallbacks?.onRead(result.length, options);
6755+
host?.buildInfoCallbacks?.onReadText(result);
67556756
buildInfo = result !== undefined ? getBuildInfo(declarationMapTextOrBuildInfoPath, result) ?? false : false;
6757+
host?.buildInfoCallbacks?.onReadEnd();
67566758
}
67576759
}
67586760
return buildInfo || undefined;

src/compiler/tsbuildPublic.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1504,9 +1504,12 @@ namespace ts {
15041504
if (existing !== undefined && existing.path === path) {
15051505
return existing.buildInfo || undefined;
15061506
}
1507+
const host = (modifiedTime ? state.host : state.compilerHost);
1508+
host.buildInfoCallbacks?.onReadStart(options);
15071509
const value = state.readFileWithCache(buildInfoPath);
1508-
if (value) (modifiedTime ? state.host : state.compilerHost).buildInfoCallbacks?.onRead(value.length, options);
1510+
host.buildInfoCallbacks?.onReadText(value);
15091511
const buildInfo = value ? ts.getBuildInfo(buildInfoPath, value) : undefined;
1512+
host.buildInfoCallbacks?.onReadEnd();
15101513
state.buildInfoCache.set(resolvedConfigPath, { path, buildInfo: buildInfo || false, modifiedTime: modifiedTime || missingFileModifiedTime });
15111514
return buildInfo;
15121515
}

src/compiler/types.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7138,7 +7138,9 @@ namespace ts {
71387138

71397139
/*@internal*/
71407140
export interface BuildInfoCallbacks {
7141-
onRead(size: number, compilerOptions: CompilerOptions | undefined): void;
7141+
onReadStart(compilerOptions: CompilerOptions | undefined): void;
7142+
onReadText(text: string | undefined): void;
7143+
onReadEnd(): void;
71427144
onWrite(size: number): void;
71437145
revertLastWrite(): void;
71447146
clearLastWrite(): void;

src/compiler/watchPublic.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@ namespace ts {
1616
buildInfo = host.getBuildInfo(buildInfoPath, compilerOptions);
1717
}
1818
else {
19+
host.buildInfoCallbacks?.onReadStart(compilerOptions);
1920
const content = host.readFile(buildInfoPath);
20-
if (!content) return undefined;
21-
host.buildInfoCallbacks?.onRead(content.length, compilerOptions);
22-
buildInfo = getBuildInfo(buildInfoPath, content);
21+
host.buildInfoCallbacks?.onReadText(content);
22+
buildInfo = content ? getBuildInfo(buildInfoPath, content) : undefined;
23+
host.buildInfoCallbacks?.onReadEnd();
2324
}
2425
if (!buildInfo || buildInfo.version !== version || !buildInfo.program) return undefined;
2526
return createBuilderProgramUsingProgramBuildInfo(buildInfo.program, buildInfoPath, host);

src/executeCommandLine/executeCommandLine.ts

Lines changed: 64 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,14 +1038,18 @@ namespace ts {
10381038
return name.replace("SolutionBuilder::", "");
10391039
}
10401040

1041-
function reportBuildInfoReadOrWriteStatistic(s: CountAndSize, type: "read" | "write") {
1042-
if (s.count) {
1041+
function reportBuildInfoReadOrWriteStatistic(s: CountAndSize | undefined, type: "read" | "write") {
1042+
if (s?.count) {
10431043
const countStatisticName = `BuildInfo ${type}`;
10441044
if (s.count !== 1) statistics.push({ name: countStatisticName, value: s.count, type: StatisticType.count });
1045-
statistics.push({ name: `BuildInfo ${type} size`, value: s.size, type: StatisticType.size });
1045+
if (s.size) statistics.push({ name: `BuildInfo ${type} size`, value: s.size, type: StatisticType.size });
1046+
if (s.textTime) statistics.push({ name: `BuildInfo ${type} time`, value: s.textTime, type: StatisticType.time });
1047+
if (s.parseTime) statistics.push({ name: `BuildInfo ${type} parsing time`, value: s.parseTime, type: StatisticType.time });
10461048
if (solutionPerformance!.hasStatistics(countStatisticName)) {
10471049
solutionPerformance!.addAggregateStatistic({ name: countStatisticName, value: s.count, type: StatisticType.count });
1048-
solutionPerformance!.addAggregateStatistic({ name: `BuildInfo ${type} size`, value: s.size, type: StatisticType.size });
1050+
if (s.size) solutionPerformance!.addAggregateStatistic({ name: `BuildInfo ${type} size`, value: s.size, type: StatisticType.size });
1051+
if (s.textTime) solutionPerformance!.addAggregateStatistic({ name: `BuildInfo ${type} time`, value: s.textTime, type: StatisticType.time });
1052+
if (s.parseTime) solutionPerformance!.addAggregateStatistic({ name: `BuildInfo ${type} parsing time`, value: s.parseTime, type: StatisticType.time });
10491053
}
10501054
}
10511055
}
@@ -1080,14 +1084,19 @@ namespace ts {
10801084
interface CountAndSize {
10811085
count: number;
10821086
size: number;
1087+
textTime: number;
1088+
parseTime: number;
10831089
}
10841090
interface LastRead {
10851091
size: number;
1086-
compilerOptions: CompilerOptions;
1092+
compilerOptions: CompilerOptions | undefined;
1093+
start: number;
1094+
textTime: number;
1095+
end: number;
10871096
}
10881097
export interface BuildInfoCallbacks {
1089-
getRead(): CountAndSize;
1090-
getWrite(): CountAndSize;
1098+
getRead(): CountAndSize | undefined;
1099+
getWrite(): CountAndSize | undefined;
10911100
getLastRead(): LastRead | undefined;
10921101
onTransferLastRead(): void;
10931102
clearLastRead(): void;
@@ -1098,16 +1107,16 @@ namespace ts {
10981107
buildInfoCallbacks?: BuildInfoCallbacks;
10991108
}
11001109

1101-
const zeroCount: CountAndSize = { count: 0, size: 0 };
1102-
11031110
function createNoOpBuildInfoCallbacks(host: CompilerHost) {
11041111
const oldCallbacks = host.buildInfoCallbacks;
11051112
oldCallbacks?.clearLastRead();
11061113
return host.buildInfoCallbacks = {
1107-
onRead: noop,
1114+
onReadStart: noop,
1115+
onReadText: noop,
1116+
onReadEnd: noop,
11081117
onWrite: noop,
1109-
getRead: () => zeroCount,
1110-
getWrite: () => zeroCount,
1118+
getRead: returnUndefined,
1119+
getWrite: returnUndefined,
11111120
getLastRead:returnUndefined,
11121121
onTransferLastRead: noop,
11131122
clearLastRead: noop,
@@ -1132,15 +1141,17 @@ namespace ts {
11321141
// This is needed to ensure that we report buildinfo read of program since its done before program is created
11331142
const oldLastRead = oldCallbacks.getLastRead();
11341143
if (oldLastRead && oldLastRead.compilerOptions === options) {
1135-
onReadOrWrite(read, oldLastRead.size);
1144+
recordRead(oldLastRead);
11361145
oldCallbacks.onTransferLastRead();
11371146
}
11381147
else {
11391148
oldCallbacks.clearLastRead();
11401149
}
11411150
}
11421151
return host.buildInfoCallbacks = {
1143-
onRead,
1152+
onReadStart,
1153+
onReadText,
1154+
onReadEnd,
11441155
onWrite,
11451156
getRead: () => read,
11461157
getWrite: () => write,
@@ -1155,19 +1166,17 @@ namespace ts {
11551166

11561167
function clear() {
11571168
Debug.assert(!oldCallbacks);
1158-
clearReadOrWrite(read);
1159-
clearReadOrWrite(write);
1169+
read.count = read.size = read.textTime = read.parseTime = 0;
1170+
write.count = write.size = 0;
11601171
lastRead = undefined;
11611172
lastWrite = undefined;
11621173
}
11631174

1164-
function clearReadOrWrite(countAndSize: CountAndSize) {
1165-
countAndSize.count = 0;
1166-
countAndSize.size = 0;
1167-
}
1168-
11691175
function onTransferLastRead() {
1170-
revertReadOrWrite(read, lastRead!.size);
1176+
read.count--;
1177+
read.size -= lastRead!.size;
1178+
read.textTime -= lastReadTextTime(lastRead!);
1179+
read.parseTime -= lastReadParseTime(lastRead!);
11711180
lastRead = undefined;
11721181
}
11731182

@@ -1183,10 +1192,33 @@ namespace ts {
11831192
countAndSize.size -= size;
11841193
}
11851194

1186-
function onRead(size: number, compilerOptions: CompilerOptions | undefined) {
1187-
onReadOrWrite(read, size);
1188-
if (compilerOptions) lastRead = { size, compilerOptions };
1189-
else lastRead = undefined;
1195+
function onReadStart(compilerOptions: CompilerOptions | undefined) {
1196+
lastRead = { start: timestamp(), compilerOptions, textTime: 0, end: 0, size: 0 };
1197+
}
1198+
1199+
function onReadText(content: string | undefined) {
1200+
lastRead!.textTime = timestamp();
1201+
lastRead!.size = content?.length ?? 0;
1202+
}
1203+
1204+
function onReadEnd() {
1205+
lastRead!.end = timestamp();
1206+
recordRead(lastRead!);
1207+
if (!lastRead!.compilerOptions) lastRead = undefined;
1208+
}
1209+
1210+
function recordRead(lastRead: LastRead) {
1211+
onReadOrWrite(read, lastRead.size);
1212+
read.textTime += lastReadTextTime(lastRead);
1213+
read.parseTime += lastReadParseTime(lastRead);
1214+
}
1215+
1216+
function lastReadTextTime(lastRead: LastRead) {
1217+
return lastRead.textTime - lastRead.start;
1218+
}
1219+
1220+
function lastReadParseTime(lastRead: LastRead) {
1221+
return lastRead.end - lastRead.textTime;
11901222
}
11911223

11921224
function onWrite(size: number) {
@@ -1201,7 +1233,7 @@ namespace ts {
12011233
}
12021234

12031235
function initializedCountAndSize(): CountAndSize {
1204-
return { count: 0, size: 0 };
1236+
return { count: 0, size: 0, textTime: 0, parseTime: 0 };
12051237
}
12061238

12071239
function isSolutionMarkOrMeasure(name: string) {
@@ -1319,15 +1351,17 @@ namespace ts {
13191351
reportStatisticalValue({ name, value: time, type: StatisticType.time }, aggregate);
13201352
}
13211353

1322-
function reportBuildInfoReadOrWriteStatistic(s: CountAndSize, type: "read" | "write") {
1323-
if (s.count) {
1354+
function reportBuildInfoReadOrWriteStatistic(s: CountAndSize | undefined, type: "read" | "write") {
1355+
if (s?.count) {
13241356
if (s.count === 1) {
13251357
solutionPerformance?.addAggregateStatistic({ name: `BuildInfo ${type}`, value: s.count, type: StatisticType.count });
13261358
}
13271359
else {
13281360
reportCountStatistic(`BuildInfo ${type}`, s.count);
13291361
}
1330-
reportStatisticalValue({ name: `BuildInfo ${type} size`, value: s.size, type: StatisticType.size }, /*aggregate*/ true);
1362+
if (s.size) reportStatisticalValue({ name: `BuildInfo ${type} size`, value: s.size, type: StatisticType.size }, /*aggregate*/ true);
1363+
if (s.textTime) reportTimeStatistic(`BuildInfo ${type} time`, s.textTime, /*aggregate*/ true);
1364+
if (s.parseTime) reportTimeStatistic(`BuildInfo ${type} parsing time`, s.parseTime, /*aggregate*/ true);
13311365
}
13321366
}
13331367
}

0 commit comments

Comments
 (0)