Patchwork D7665: dirstate: when calling rebuild(), avoid some N^2 codepaths

login
register
mail settings
Submitter phabricator
Date Dec. 17, 2019, 12:02 a.m.
Message ID <e7e7000a845fdd6736b53a0568b37559@localhost.localdomain>
Download mbox | patch
Permalink /patch/43893/
State Not Applicable
Headers show

Comments

phabricator - Dec. 17, 2019, 12:02 a.m.
Closed by commit rHG7eb6a2680ae6: dirstate: when calling rebuild(), avoid some N^2 codepaths (authored by spectral).
This revision was automatically updated to reflect the committed changes.
This revision was not accepted when it landed; it landed in state "Needs Review".

CHANGED PRIOR TO COMMIT
  https://phab.mercurial-scm.org/D7665?vs=18721&id=18782#toc

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D7665?vs=18721&id=18782

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D7665/new/

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

AFFECTED FILES
  mercurial/dirstate.py

CHANGE DETAILS




To: spectral, #hg-reviewers
Cc: martinvonz, mercurial-devel

Patch

diff --git a/mercurial/dirstate.py b/mercurial/dirstate.py
--- a/mercurial/dirstate.py
+++ b/mercurial/dirstate.py
@@ -603,19 +603,34 @@ 
     def rebuild(self, parent, allfiles, changedfiles=None):
         if changedfiles is None:
             # Rebuild entire dirstate
-            changedfiles = allfiles
+            to_lookup = allfiles
+            to_drop = []
             lastnormaltime = self._lastnormaltime
             self.clear()
             self._lastnormaltime = lastnormaltime
+        elif len(changedfiles) < 10:
+            # Avoid turning allfiles into a set, which can be expensive if it's
+            # large.
+            to_lookup = []
+            to_drop = []
+            for f in changedfiles:
+                if f in allfiles:
+                    to_lookup.append(f)
+                else:
+                    to_drop.append(f)
+        else:
+            changedfilesset = set(changedfiles)
+            to_lookup = changedfilesset & set(allfiles)
+            to_drop = changedfilesset - to_lookup
 
         if self._origpl is None:
             self._origpl = self._pl
         self._map.setparents(parent, nullid)
-        for f in changedfiles:
-            if f in allfiles:
-                self.normallookup(f)
-            else:
-                self.drop(f)
+
+        for f in to_lookup:
+            self.normallookup(f)
+        for f in to_drop:
+            self.drop(f)
 
         self._dirty = True