Skip to content

Commit

Permalink
sys: Use readdir withFileTypes option to skip lots of stat syscalls (#…
Browse files Browse the repository at this point in the history
…35286)

This makes walking large directory trees much more efficient on Node
10.10 or later.

See:
https://lwn.net/Articles/606995/
https://www.python.org/dev/peps/pep-0471/
nodejs/node#22020
https://nodejs.org/en/blog/release/v10.10.0/

Signed-off-by: Anders Kaseorg <andersk@mit.edu>
  • Loading branch information
andersk authored and amcasey committed Jan 15, 2020
1 parent 1dafd09 commit 64704a1
Showing 1 changed file with 19 additions and 9 deletions.
28 changes: 19 additions & 9 deletions src/compiler/sys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1617,23 +1617,32 @@ namespace ts {
function getAccessibleFileSystemEntries(path: string): FileSystemEntries {
perfLogger.logEvent("ReadDir: " + (path || "."));
try {
const entries = _fs.readdirSync(path || ".").sort();
const entries = _fs.readdirSync(path || ".", { withFileTypes: true });
const files: string[] = [];
const directories: string[] = [];
for (const entry of entries) {
for (const dirent of entries) {
// withFileTypes is not supported before Node 10.10.
const entry = typeof dirent === "string" ? dirent : dirent.name;

// This is necessary because on some file system node fails to exclude
// "." and "..". See https://github.com/nodejs/node/issues/4002
if (entry === "." || entry === "..") {
continue;
}
const name = combinePaths(path, entry);

let stat: any;
try {
stat = _fs.statSync(name);
if (typeof dirent === "string" || dirent.isSymbolicLink()) {
const name = combinePaths(path, entry);

try {
stat = _fs.statSync(name);
}
catch (e) {
continue;
}
}
catch (e) {
continue;
else {
stat = dirent;
}

if (stat.isFile()) {
Expand All @@ -1643,6 +1652,8 @@ namespace ts {
directories.push(entry);
}
}
files.sort();
directories.sort();
return { files, directories };
}
catch (e) {
Expand Down Expand Up @@ -1677,8 +1688,7 @@ namespace ts {
}

function getDirectories(path: string): string[] {
perfLogger.logEvent("ReadDir: " + path);
return filter<string>(_fs.readdirSync(path), dir => fileSystemEntryExists(combinePaths(path, dir), FileSystemEntryKind.Directory));
return getAccessibleFileSystemEntries(path).directories.slice();
}

function realpath(path: string): string {
Expand Down

0 comments on commit 64704a1

Please sign in to comment.