[PATCH 3 of 3] use per-directory clustered stat calls even in cases where known tree is walked

Petr Kodl petrkodl at gmail.com
Tue Sep 30 13:54:20 CDT 2008


# HG changeset patch
# User Petr Kodl <petrkodl at gmail.com>
# Date 1222800830 14400
# Node ID 0f4f092ba9115b9d0050d31b544e77d90659e68e
# Parent  4c4f0e0856051aaee373ede840315a05c8e1563e
use per-directory clustered stat calls even in cases where known tree is walked

This allows diff and other calls walking known tree to benefit from osutil.c.

Some timings from clean tree with ~23k files

no patch

hg st    .7s
hg diff  3s

with patch

hg diff  .7s

diff -r 4c4f0e085605 -r 0f4f092ba911 mercurial/dirstate.py
--- a/mercurial/dirstate.py	Tue Sep 30 14:52:06 2008 -0400
+++ b/mercurial/dirstate.py	Tue Sep 30 14:53:50 2008 -0400
@@ -505,6 +505,21 @@
                         if (nf in dmap or not ignore(nf)) and matchfn(nf):
                             results[nf] = None
 
+        # if work is empty set it to list of known repo dirs
+        # this eliminates per-file lstat calls in step 3
+        # and replaces it with per-directory call in step 2
+        # recursive walking can be turned off as _dirs contains
+        # all directories already
+        # - this optimization is win32 specific and depends on osutil.c
+        #   performance characteristics
+        # - avoid the inversion if explicit files are specified on command
+        #   line
+        recursive = 1
+        if sys.platform=='win32' and not len(match.files()) and not len(work):
+            work.append('.')
+            work.extend(self._dirs.keys())
+            recursive = 0
+
         # step 2: visit subdirectories
         while work:
             nd = work.pop()
@@ -519,7 +534,7 @@
                 nf = normalize(nd and (nd + "/" + f) or f, True)
                 if nf not in results:
                     if kind == dirkind:
-                        if not ignore(nf):
+                        if recursive and not ignore(nf):
                             wadd(nf)
                         if nf in dmap and matchfn(nf):
                             results[nf] = None


More information about the Mercurial-devel mailing list