From 3bef954304cb4b99ab30643c49f0727d917a5306 Mon Sep 17 00:00:00 2001 From: Rob Hogan Date: Mon, 27 Feb 2023 06:03:50 -0800 Subject: [PATCH] Add `unstable_preferTreeFS` to use TreeFS without enabling symlinks Summary: This allows the use of the new symlink-supporting prefix-tree `FileSystem` implementation, `TreeFS` *without* enabling symlinks. The main purpose of this is to allow like-for-like performance comparisons of operations at this level - in particular, startup involving assembling the tree, and resolution under the new `exists` implementation. Because `HasteFS` and `TreeFS` should have identical outputs on regular files, this setting is *not* a cache key component (unlike `resolver.unstable_enableSymlinks`). Reviewed By: motiz88 Differential Revision: D43539702 fbshipit-source-id: 92639845f42d6c7a3d626de9853c9c360b45367a --- .../__snapshots__/loadConfig-test.js.snap | 4 ++++ packages/metro-config/src/configTypes.flow.js | 7 ++++--- packages/metro-config/src/defaults/index.js | 7 ++++--- packages/metro-file-map/src/index.js | 19 ++++++++++++------- .../DependencyGraph/createHasteMap.js | 1 + 5 files changed, 25 insertions(+), 13 deletions(-) diff --git a/packages/metro-config/src/__tests__/__snapshots__/loadConfig-test.js.snap b/packages/metro-config/src/__tests__/__snapshots__/loadConfig-test.js.snap index dfcf5b91cf..996f9c7780 100644 --- a/packages/metro-config/src/__tests__/__snapshots__/loadConfig-test.js.snap +++ b/packages/metro-config/src/__tests__/__snapshots__/loadConfig-test.js.snap @@ -169,6 +169,7 @@ Object { "interval": 30000, "timeout": 5000, }, + "unstable_preferTreeFS": false, "watchman": Object { "deferStates": Array [ "hg.update", @@ -347,6 +348,7 @@ Object { "interval": 30000, "timeout": 5000, }, + "unstable_preferTreeFS": false, "watchman": Object { "deferStates": Array [ "hg.update", @@ -525,6 +527,7 @@ Object { "interval": 30000, "timeout": 5000, }, + "unstable_preferTreeFS": false, "watchman": Object { "deferStates": Array [ "hg.update", @@ -703,6 +706,7 @@ Object { "interval": 30000, "timeout": 5000, }, + "unstable_preferTreeFS": false, "watchman": Object { "deferStates": Array [ "hg.update", diff --git a/packages/metro-config/src/configTypes.flow.js b/packages/metro-config/src/configTypes.flow.js index e95e0d83e7..96914796dc 100644 --- a/packages/metro-config/src/configTypes.flow.js +++ b/packages/metro-config/src/configTypes.flow.js @@ -187,15 +187,16 @@ type SymbolicatorConfigT = { type WatcherConfigT = { additionalExts: $ReadOnlyArray, - watchman: { - deferStates: $ReadOnlyArray, - }, healthCheck: { enabled: boolean, interval: number, timeout: number, filePrefix: string, }, + unstable_preferTreeFS: boolean, + watchman: { + deferStates: $ReadOnlyArray, + }, }; export type InputConfigT = $Shape<{ diff --git a/packages/metro-config/src/defaults/index.js b/packages/metro-config/src/defaults/index.js index ff3e3d21a7..3e8622df8f 100644 --- a/packages/metro-config/src/defaults/index.js +++ b/packages/metro-config/src/defaults/index.js @@ -138,15 +138,16 @@ const getDefaultValues = (projectRoot: ?string): ConfigT => ({ }, watcher: { additionalExts, - watchman: { - deferStates: ['hg.update'], - }, healthCheck: { enabled: false, filePrefix: '.metro-health-check', interval: 30000, timeout: 5000, }, + unstable_preferTreeFS: false, + watchman: { + deferStates: ['hg.update'], + }, }, cacheStores: [ new FileStore({ diff --git a/packages/metro-file-map/src/index.js b/packages/metro-file-map/src/index.js index df0c880376..7787dd8be4 100644 --- a/packages/metro-file-map/src/index.js +++ b/packages/metro-file-map/src/index.js @@ -93,17 +93,17 @@ export type InputOptions = $ReadOnly<{ dependencyExtractor?: ?string, hasteImplModulePath?: ?string, + cacheManagerFactory?: ?CacheManagerFactory, + console?: Console, + healthCheck: HealthCheckOptions, + maxWorkers: number, perfLoggerFactory?: ?PerfLoggerFactory, resetCache?: ?boolean, - maxWorkers: number, throwOnModuleCollision?: ?boolean, + unstable_preferTreeFS?: ?boolean, useWatchman?: ?boolean, - watchmanDeferStates?: $ReadOnlyArray, watch?: ?boolean, - console?: Console, - cacheManagerFactory?: ?CacheManagerFactory, - - healthCheck: HealthCheckOptions, + watchmanDeferStates?: $ReadOnlyArray, }>; type HealthCheckOptions = $ReadOnly<{ @@ -120,6 +120,7 @@ type InternalOptions = { resetCache: ?boolean, maxWorkers: number, throwOnModuleCollision: boolean, + unstable_preferTreeFS: boolean, useWatchman: boolean, watch: boolean, watchmanDeferStates: $ReadOnlyArray, @@ -312,6 +313,7 @@ export default class HasteMap extends EventEmitter { perfLoggerFactory: options.perfLoggerFactory, resetCache: options.resetCache, throwOnModuleCollision: !!options.throwOnModuleCollision, + unstable_preferTreeFS: !!options.unstable_preferTreeFS, useWatchman: options.useWatchman == null ? true : options.useWatchman, watch: !!options.watch, watchmanDeferStates: options.watchmanDeferStates ?? [], @@ -359,7 +361,10 @@ export default class HasteMap extends EventEmitter { const rootDir = this._options.rootDir; const fileData = initialData.files; this._startupPerfLogger?.point('constructFileSystem_start'); - const FileSystem = this._options.enableSymlinks ? TreeFS : HasteFS; + const useTreeFS = + this._options.enableSymlinks || this._options.unstable_preferTreeFS; + this._startupPerfLogger?.annotate({bool: {useTreeFS}}); + const FileSystem = useTreeFS ? TreeFS : HasteFS; const fileSystem = new FileSystem({ files: fileData, rootDir, diff --git a/packages/metro/src/node-haste/DependencyGraph/createHasteMap.js b/packages/metro/src/node-haste/DependencyGraph/createHasteMap.js index 5ecf812f86..bd40ed933d 100644 --- a/packages/metro/src/node-haste/DependencyGraph/createHasteMap.js +++ b/packages/metro/src/node-haste/DependencyGraph/createHasteMap.js @@ -90,6 +90,7 @@ function createHasteMap( rootDir: config.projectRoot, roots: config.watchFolders, throwOnModuleCollision: options?.throwOnModuleCollision ?? true, + unstable_preferTreeFS: config.watcher.unstable_preferTreeFS, useWatchman: config.resolver.useWatchman, watch: options?.watch == null ? !ci.isCI : options.watch, watchmanDeferStates: config.watcher.watchman.deferStates,