[PATCH 1 of 1] dirstate: optimisation of walk

Simon Heimberg simohe at besonet.ch
Thu May 14 09:59:25 CDT 2009


# HG changeset patch
# User Simon Heimberg <simohe at besonet.ch>
# Date 1242291045 -7200
# Node ID 635197d4f31e44206169314755a16e0fcc835acf
# Parent  7190bdb6ba8c5fcedf9efa61d31cbeca3ae686cb
dirstate: optimisation of walk

Only execute step 3 when it is necessary. Skip it when nothing will match or all
matches have been found in step 1.
Find more matches in step 1.
Little optimisation by using matchfn() instead of match() in step 3.
Little optimisation in match by using self.exact, which uses a set.
The changes in match are for detecting the functions in in dirstate.

diff -r 7190bdb6ba8c -r 635197d4f31e mercurial/dirstate.py
--- a/mercurial/dirstate.py	Fre Mai 08 17:53:22 2009 +0200
+++ b/mercurial/dirstate.py	Don Mai 14 10:50:45 2009 +0200
@@ -484,6 +484,10 @@
         join = self._join
         work = []
         wadd = work.append
+        dostep3 = match.anypats() or matchfn == util.always
+        onlystep1 = matchfn == match.exact or matchfn == util.never
+        if onlystep1:
+            dirignore = util.always
 
         files = set(match.files())
         if not files or '.' in files:
@@ -500,6 +504,10 @@
                 st = lstat(join(nf))
                 kind = getkind(st.st_mode)
                 if kind == dirkind:
+                    dostep3 = True
+                    if nf in dmap:
+                        #file deleted on disc but still in dirstate
+                        results[nf] = None
                     if not dirignore(nf):
                         wadd(nf)
                 elif kind == regkind or kind == lnkkind:
@@ -512,14 +520,20 @@
                 keep = False
                 prefix = nf + "/"
                 for fn in dmap:
-                    if nf == fn or fn.startswith(prefix):
+                    if nf == fn:
+                        if matchfn(nf):
+                            results[nf] = None
+                        keep = True
+                        break
+                    elif fn.startswith(prefix):
+                        dostep3 = True
                         keep = True
                         break
                 if not keep:
                     if inst.errno != errno.ENOENT:
                         fwarn(ff, inst.strerror)
                     elif badfn(ff, inst.strerror):
-                        if (nf in dmap or not ignore(nf)) and matchfn(nf):
+                        if nf not in results and not ignore(nf) and matchfn(nf):
                             results[nf] = None
 
         # step 2: visit subdirectories
@@ -557,11 +571,12 @@
                         results[nf] = None
 
         # step 3: report unseen items in the dmap hash
-        visit = sorted([f for f in dmap if f not in results and match(f)])
-        for nf, st in zip(visit, util.statfiles([join(i) for i in visit])):
-            if not st is None and not getkind(st.st_mode) in (regkind, lnkkind):
-                st = None
-            results[nf] = st
+        if dostep3 and not onlystep1:
+            visit = sorted([f for f in dmap if f not in results and matchfn(f)])
+            for nf, st in zip(visit, util.statfiles([join(i) for i in visit])):
+                if not st is None and not getkind(st.st_mode) in (regkind, lnkkind):
+                    st = None
+                results[nf] = st
 
         del results['.hg']
         return results
diff -r 7190bdb6ba8c -r 635197d4f31e mercurial/match.py
--- a/mercurial/match.py	Fre Mai 08 17:53:22 2009 +0200
+++ b/mercurial/match.py	Don Mai 14 10:50:45 2009 +0200
@@ -37,15 +37,15 @@
 
 class always(_match):
     def __init__(self, root, cwd):
-        _match.__init__(self, root, cwd, [], lambda f: True, False)
+        _match.__init__(self, root, cwd, [], util.always, False)
 
 class never(_match):
     def __init__(self, root, cwd):
-        _match.__init__(self, root, cwd, [], lambda f: False, False)
+        _match.__init__(self, root, cwd, [], util.never, False)
 
 class exact(_match):
     def __init__(self, root, cwd, files):
-        _match.__init__(self, root, cwd, files, lambda f: f in files, False)
+        _match.__init__(self, root, cwd, files, self.exact, False)
 
 class match(_match):
     def __init__(self, root, cwd, patterns, include, exclude, default):


More information about the Mercurial-devel mailing list