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!
This commit is contained in:
Andrew Casey
2019-10-16 11:24:24 -07:00
parent 178417f431
commit 4ed80b62df
2 changed files with 30 additions and 9 deletions

View File

@@ -151,13 +151,16 @@ namespace ts {
function writeFile(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void) {
try {
performance.mark("beforeIOWrite");
ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName)));
if (isWatchSet(options) && system.createHash && system.getModifiedTime) {
writeFileIfUpdated(fileName, data, writeByteOrderMark);
// PERF: Checking for directory existence is expensive.
// Instead, assume the directory exists and fall back
// to creating it if the file write fails.
try {
writeFileWorker(fileName, data, writeByteOrderMark);
}
else {
system.writeFile(fileName, data, writeByteOrderMark);
catch (_) {
ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName)));
writeFileWorker(fileName, data, writeByteOrderMark);
}
performance.mark("afterIOWrite");
@@ -170,6 +173,15 @@ namespace ts {
}
}
function writeFileWorker(fileName: string, data: string, writeByteOrderMark: boolean) {
if (isWatchSet(options) && system.createHash && system.getModifiedTime) {
writeFileIfUpdated(fileName, data, writeByteOrderMark);
}
else {
system.writeFile(fileName, data, writeByteOrderMark);
}
}
function getDefaultLibLocation(): string {
return getDirectoryPath(normalizePath(system.getExecutingFilePath()));
}

View File

@@ -541,11 +541,20 @@ namespace ts {
// patch writefile to create folder before writing the file
const originalWriteFile = sys.writeFile;
sys.writeFile = (path, data, writeBom) => {
const directoryPath = getDirectoryPath(normalizeSlashes(path));
if (directoryPath && !sys.directoryExists(directoryPath)) {
recursiveCreateDirectory(directoryPath, sys);
// PERF: Checking for directory existence is expensive.
// Instead, assume the directory exists and fall back
// to creating it if the file write fails.
try {
originalWriteFile.call(sys, path, data, writeBom);
}
catch (_) {
const directoryPath = getDirectoryPath(normalizeSlashes(path));
if (directoryPath && !sys.directoryExists(directoryPath)) {
recursiveCreateDirectory(directoryPath, sys);
}
originalWriteFile.call(sys, path, data, writeBom);
}
originalWriteFile.call(sys, path, data, writeBom);
};
}