Skip to content

Commit 4ed80b6

Browse files
committed
Stop pre-emptively creating directories
Checking for directory existence is expensive and frequently indicates success. Instead of pre-emptively creating the directory containing a file to be written, attempt to create the file and only do the directory scaffolding if the write fails. Appears to reduce file write time by 10-20% for a file-I/O heavy partner build. Thanks to @rbuckton for the suggestion!
1 parent 178417f commit 4ed80b6

File tree

2 files changed

+30
-9
lines changed

2 files changed

+30
-9
lines changed

src/compiler/program.ts

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -151,13 +151,16 @@ namespace ts {
151151
function writeFile(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void) {
152152
try {
153153
performance.mark("beforeIOWrite");
154-
ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName)));
155154

156-
if (isWatchSet(options) && system.createHash && system.getModifiedTime) {
157-
writeFileIfUpdated(fileName, data, writeByteOrderMark);
155+
// PERF: Checking for directory existence is expensive.
156+
// Instead, assume the directory exists and fall back
157+
// to creating it if the file write fails.
158+
try {
159+
writeFileWorker(fileName, data, writeByteOrderMark);
158160
}
159-
else {
160-
system.writeFile(fileName, data, writeByteOrderMark);
161+
catch (_) {
162+
ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName)));
163+
writeFileWorker(fileName, data, writeByteOrderMark);
161164
}
162165

163166
performance.mark("afterIOWrite");
@@ -170,6 +173,15 @@ namespace ts {
170173
}
171174
}
172175

176+
function writeFileWorker(fileName: string, data: string, writeByteOrderMark: boolean) {
177+
if (isWatchSet(options) && system.createHash && system.getModifiedTime) {
178+
writeFileIfUpdated(fileName, data, writeByteOrderMark);
179+
}
180+
else {
181+
system.writeFile(fileName, data, writeByteOrderMark);
182+
}
183+
}
184+
173185
function getDefaultLibLocation(): string {
174186
return getDirectoryPath(normalizePath(system.getExecutingFilePath()));
175187
}

src/compiler/sys.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -541,11 +541,20 @@ namespace ts {
541541
// patch writefile to create folder before writing the file
542542
const originalWriteFile = sys.writeFile;
543543
sys.writeFile = (path, data, writeBom) => {
544-
const directoryPath = getDirectoryPath(normalizeSlashes(path));
545-
if (directoryPath && !sys.directoryExists(directoryPath)) {
546-
recursiveCreateDirectory(directoryPath, sys);
544+
// PERF: Checking for directory existence is expensive.
545+
// Instead, assume the directory exists and fall back
546+
// to creating it if the file write fails.
547+
try {
548+
originalWriteFile.call(sys, path, data, writeBom);
549+
}
550+
catch (_) {
551+
const directoryPath = getDirectoryPath(normalizeSlashes(path));
552+
if (directoryPath && !sys.directoryExists(directoryPath)) {
553+
recursiveCreateDirectory(directoryPath, sys);
554+
}
555+
556+
originalWriteFile.call(sys, path, data, writeBom);
547557
}
548-
originalWriteFile.call(sys, path, data, writeBom);
549558
};
550559
}
551560

0 commit comments

Comments
 (0)