Skip to content

metro-file-map: Start FallbackWatcher without stat-ing every file - #2105

Draft
robhogan wants to merge 1 commit into
pr2104from
pr2105
Draft

robhogan wants to merge 1 commit into
pr2104from
pr2105

Conversation

@robhogan

@robhogan robhogan commented Oct 25, 2026 •

Copy link
Copy Markdown
Collaborator

Without Watchman, Metro watches with FallbackWatcher on Linux and Windows. Its startup walk lstats every entry, files included, just to learn its type:

const visit = async (entry: string) => {
let stats;
let names;
try {
stats = await fsPromises.lstat(entry);
if (!stats.isDirectory()) {
if (stats.isSymbolicLink()) {
symlinkCallback(entry, stats);
} else if (stats.isFile()) {
fileCallback(entry, stats);
}

This walks by the types readdir reports instead. A directory that appears while watching still needs stats for its events, so that walk now stats only the entries it reports. The walk also now descends into a watch root that's a symlink, as the crawler does.

Benchmark

This takes 40% off watch-mode startup on Linux (1,617ms -> 964ms) and 20% off on Windows. macOS uses NativeWatcher, so it's unaffected.

main #2104 This PR vs main vs #2104
Linux: Watch-mode start, warm cache 1,896ms 1,617ms 964ms -49.2% (-49.7% to -48.7%) -40.4% (-40.7% to -39.7%)
Windows: Watch-mode start, warm cache 2,554ms 2,429ms 1,939ms -24.1% (-24.7% to -23.7%) -20.2% (-20.9% to -19.8%)
Linux: Watch-mode start, cold cache 1,882ms 1,599ms 972ms -48.4% (-48.9% to -48.1%) -39.2% (-39.9% to -39.0%)
Windows: Watch-mode start, cold cache 2,547ms 2,419ms 1,911ms -25.0% (-25.3% to -24.6%) -21.0% (-21.3% to -20.5%)

Changelog

 - **[Performance]**: metro-file-map: Start the file watcher without stat-ing every file (Linux and Windows, without Watchman)

Test plan

New unit test that startup doesn't lstat anything it finds. Benchmark as in #2104.

@robhogan
robhogan added this pull request to stack #2109 October 25, 2026 15:22
@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Oct 25, 2026
@robhogan
robhogan force-pushed the pr2105 branch 2 times, most recently from f60f8cc to 5df0bf6 Compare October 25, 2026 20:13
Without Watchman, Metro watches with `FallbackWatcher` on Linux and Windows. Its startup walk `lstat`s every entry, files included, just to learn its type:

https://github.com/react/metro/blob/56efab302200568c919ac1b3c28dacf8d84fc692/packages/metro-file-map/src/watchers/FallbackWatcher.js#L505-L515

This walks by the types `readdir` reports instead. A directory that appears while watching still needs stats for its events, so that walk now stats only the entries it reports. The walk also now descends into a watch root that's a symlink, as the crawler does.

## Benchmark

This takes 40% off watch-mode startup on Linux (1,617ms -> 964ms) and 20% off on Windows. macOS uses `NativeWatcher`, so it's unaffected.

|  | `main` | #2104 | This PR | vs `main` | vs #2104 |
|---|---|---|---|---|---|
| Linux: Watch-mode start, warm cache | 1,896ms | 1,617ms | 964ms | -49.2% (-49.7% to -48.7%) | -40.4% (-40.7% to -39.7%) |
| Windows: Watch-mode start, warm cache | 2,554ms | 2,429ms | 1,939ms | -24.1% (-24.7% to -23.7%) | -20.2% (-20.9% to -19.8%) |
| Linux: Watch-mode start, cold cache | 1,882ms | 1,599ms | 972ms | -48.4% (-48.9% to -48.1%) | -39.2% (-39.9% to -39.0%) |
| Windows: Watch-mode start, cold cache | 2,547ms | 2,419ms | 1,911ms | -25.0% (-25.3% to -24.6%) | -21.0% (-21.3% to -20.5%) |

## Changelog

```
 - **[Performance]**: metro-file-map: Start the file watcher without stat-ing every file (Linux and Windows, without Watchman)
```

## Test plan

New unit test that startup doesn't `lstat` anything it finds. Benchmark as in #2104.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant