D894: fsmonitor: warn when fsmonitor could be used

indygreg (Gregory Szorc) phabricator at mercurial-scm.org
Sun Oct 1 22:49:41 UTC 2017


indygreg created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  fsmonitor can significantly speed up operations on large working
  directories. But fsmonitor isn't enabled by default, so naive users
  may not realize there is a potential to make Mercurial faster.
  
  This commit introduces a warning to working directory updates when
  fsmonitor could be used.
  
  The following conditions must be met:
  
  - Working directory is previously empty
  - New working directory adds >= N files (currently 50,000)
  - Running on Linux or MacOS
  - fsmonitor not enabled
  - Warning not disabled via config override
  
  Because of the empty working directory restriction, most users will
  only see this warning during `hg clone` (assuming very few users
  actually do an `hg up null`).
  
  The addition of a warning may be considered a BC change. However, clone
  has printed warnings before. Until recently, Mercurial printed a warning
  with the server's certificate fingerprint when it wasn't explicitly
  trusted for example. The warning goes to stderr. So it shouldn't
  interfere with scripts parsing meaningful output.
  
  The OS restriction was on the advice of Facebook engineers, who only
  feel confident with watchman's stability on the supported platforms.
  
  .. feature::
  
    Print warning when fsmonitor isn't being used on a large repository

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D894

AFFECTED FILES
  hgext/fsmonitor/__init__.py
  mercurial/configitems.py
  mercurial/merge.py
  tests/hghave.py
  tests/test-fsmonitor-warning.t

CHANGE DETAILS

diff --git a/tests/test-fsmonitor-warning.t b/tests/test-fsmonitor-warning.t
new file mode 100644
--- /dev/null
+++ b/tests/test-fsmonitor-warning.t
@@ -0,0 +1,94 @@
+Cloning without fsmonitor enabled does not print a warning for small repos
+
+  $ hg init source
+  $ cd source
+  $ touch file1 file2 file3 file4
+  $ hg -q commit -A -m initial
+  $ touch file5
+  $ hg -q commit -A -m 'add file5'
+  $ cd ..
+
+  $ hg clone source dest-default
+  updating to branch default
+  5 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+Lower the warning threshold to simulate a large repo
+
+  $ cat >> $HGRCPATH << EOF
+  > [fsmonitor]
+  > warn_update_file_count = 4
+  > EOF
+
+We should see a warning about no fsmonitor on supported platforms
+
+#if linuxormacos no-fsmonitor
+
+  $ hg clone source dest-nofsmonitor
+  updating to branch default
+  (warning: large working directory being used without fsmonitor enabled; enable fsmonitor to improve performance; see "hg help -e fsmonitor")
+  5 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+#else
+
+  $ hg clone source dest-nofsmonitor
+  updating to branch default
+  5 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+#endif
+
+We should not see warning about fsmonitor when it is enabled
+
+#if fsmonitor
+
+  $ hg clone source dest-fsmonitor
+  updating to branch default
+  5 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+#endif
+
+We can disable the fsmonitor warning
+
+  $ hg --config fsmonitor.warn_when_unused=false clone source dest-disable-warning
+  updating to branch default
+  5 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+Loaded fsmonitor but disabled in config should still print warning
+
+#if linuxormacos fsmonitor
+
+  $ hg --config fsmonitor.mode=off clone source dest-mode-off
+  updating to branch default
+  (warning: large working directory being used without fsmonitor enabled; enable fsmonitor to improve performance; see "hg help -e fsmonitor") (fsmonitor !)
+  5 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+#endif
+
+Warning not printed if working directory isn't empty
+
+  $ hg -q clone source dest-update
+  (warning: large working directory being used without fsmonitor enabled; enable fsmonitor to improve performance; see "hg help -e fsmonitor") (?)
+  $ cd dest-update
+  $ hg up 4c436bafb4ab
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ hg up 9637229078ea
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+`hg update` from null revision also prints
+
+  $ hg up null
+  0 files updated, 0 files merged, 5 files removed, 0 files unresolved
+
+#if linuxormacos no-fsmonitor
+
+  $ hg up 9637229078ea
+  (warning: large working directory being used without fsmonitor enabled; enable fsmonitor to improve performance; see "hg help -e fsmonitor")
+  5 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+#else
+
+  $ hg up 9637229078ea
+  5 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+#endif
+
+  $ cd ..
diff --git a/tests/hghave.py b/tests/hghave.py
--- a/tests/hghave.py
+++ b/tests/hghave.py
@@ -554,6 +554,11 @@
     except ImportError:
         return False
 
+ at check('linuxormacos', 'Linux or MacOS')
+def has_linuxormacos():
+    # This isn't a perfect test for MacOS. But it is sufficient for our needs.
+    return sys.platform.startswith(('linux', 'darwin'))
+
 @check("docker", "docker support")
 def has_docker():
     pat = br'A self-sufficient runtime for'
diff --git a/mercurial/merge.py b/mercurial/merge.py
--- a/mercurial/merge.py
+++ b/mercurial/merge.py
@@ -25,6 +25,7 @@
 from . import (
     copies,
     error,
+    extensions,
     filemerge,
     match as matchmod,
     obsutil,
@@ -1713,6 +1714,38 @@
             # note that we're in the middle of an update
             repo.vfs.write('updatestate', p2.hex())
 
+        # Advertise fsmonitor when its presence could be useful.
+        #
+        # We only advertise when performing an update from an empty working
+        # directory. This typically only occurs during initial clone.
+        #
+        # We give users a mechanism to disable the warning in case it is
+        # annoying.
+        #
+        # We only allow on Linux and MacOS because that's where fsmonitor is
+        # considered stable.
+        fsmonitorwarning = repo.ui.configbool('fsmonitor', 'warn_when_unused')
+        fsmonitorthreshold = repo.ui.configint('fsmonitor',
+                                               'warn_update_file_count')
+        try:
+            extensions.find('fsmonitor')
+            fsmonitorenabled = repo.ui.config('fsmonitor', 'mode') != 'off'
+            # We intentionally don't look at whether fsmonitor has disabled
+            # itself because a) fsmonitor may have already printed a warning
+            # b) we only care about the config state here.
+        except KeyError:
+            fsmonitorenabled = False
+
+        if fsmonitorwarning \
+                and not fsmonitorenabled \
+                and p1.node() == nullid \
+                and len(actions['g']) >= fsmonitorthreshold \
+                and pycompat.sysplatform.startswith(('linux', 'darwin')):
+            repo.ui.warn(
+                _('(warning: large working directory being used without '
+                  'fsmonitor enabled; enable fsmonitor to improve performance; '
+                  'see "hg help -e fsmonitor")\n'))
+
         stats = applyupdates(repo, actions, wc, p2, overwrite, labels=labels)
         wc.flushall()
 
diff --git a/mercurial/configitems.py b/mercurial/configitems.py
--- a/mercurial/configitems.py
+++ b/mercurial/configitems.py
@@ -275,6 +275,12 @@
 coreconfigitem('format', 'usestore',
     default=True,
 )
+coreconfigitem('fsmonitor', 'warn_when_unused',
+    default=True,
+)
+coreconfigitem('fsmonitor', 'warn_update_file_count',
+    default=50000,
+)
 coreconfigitem('hostsecurity', 'ciphers',
     default=None,
 )
diff --git a/hgext/fsmonitor/__init__.py b/hgext/fsmonitor/__init__.py
--- a/hgext/fsmonitor/__init__.py
+++ b/hgext/fsmonitor/__init__.py
@@ -18,6 +18,9 @@
 repository as necessary. You'll need to install Watchman from
 https://facebook.github.io/watchman/ and make sure it is in your PATH.
 
+fsmonitor is incompatible with the largefiles and eol extensions, and
+will disable itself if any of those are active.
+
 The following configuration options exist:
 
 ::
@@ -58,9 +61,22 @@
 that can outpace the IPC overhead of getting the result data for the full repo
 from Watchman. Defaults to false.
 
-fsmonitor is incompatible with the largefiles and eol extensions, and
-will disable itself if any of those are active.
+::
+
+    [fsmonitor]
+    warn_when_unused = (boolean)
+
+Whether to print a warning during certain operations when fsmonitor would be
+beneficial to performance but isn't enabled.
 
+::
+
+    [fsmonitor]
+    warn_update_file_count = (integer)
+
+If ``warn_when_unused`` is set and fsmonitor isn't enabled, a warning will
+be printed during working directory updates if this many files will be
+created.
 '''
 
 # Platforms Supported



To: indygreg, #hg-reviewers
Cc: mercurial-devel


More information about the Mercurial-devel mailing list