[PATCH 3 of 3] dirstate: minimize number of separate lstat calls
Petr Kodl
petrkodl at gmail.com
Fri Sep 5 15:24:37 CDT 2008
# HG changeset patch
# User Petr Kodl <petrkodl at gmail.com>
# Date 1220646245 14400
# Node ID 5cc4fb7d9dabb55f9a56a9813df0aaeeddbd8224
# Parent d06d4ec75479dc1a065312751f0f3c86e4bac6c4
dirstate: minimize number of separate lstat calls
diff -r d06d4ec75479 -r 5cc4fb7d9dab mercurial/dirstate.py
--- a/mercurial/dirstate.py Fri Sep 05 16:24:05 2008 -0400
+++ b/mercurial/dirstate.py Fri Sep 05 16:24:05 2008 -0400
@@ -509,6 +509,27 @@
if (nf in dmap or not ignore(nf)) and matchfn(nf):
results[nf] = None
+ # if there are no directories to visit
+ # try to consolidate number of lstat calls anyway
+ # this reduces # of lstat calls from O(#files) to O(#directories)
+ # assuming the lstat over files in dir is faster than lstat
+ # over randomly spread files which seems to be the case at least for
+ # Win32 and Linux
+ # option 2 would be to never skip step 2 but this could be expensive in
+ # extremely sparse trees (many files / small # tracked)
+ recurse = 1
+ if not work:
+ visit_dirs = {}
+ for x in [f for f in dmap if f not in results and match(f)]:
+ visit_dirs[os.path.dirname(x)]=None
+ if '' in visit_dirs:
+ visit_dirs.pop('')
+ visit_dirs['.']=None
+ visit_dirs = visit_dirs.keys()
+ visit_dirs.sort()
+ work += visit_dirs
+ recurse=0
+
# step 2: visit subdirectories
while work:
nd = work.pop()
@@ -529,7 +550,7 @@
nf = normalize(nd and (nd + "/" + f) or f, True)
if nf not in results:
if kind == dirkind:
- if not ignore(nf):
+ if not ignore(nf) and recurse:
wadd(nf)
if nf in dmap and matchfn(nf):
results[nf] = None
More information about the Mercurial-devel
mailing list