[PATCH 2 of 5] hidden: optimise hidden set computation

pierre-yves.david at logilab.fr pierre-yves.david at logilab.fr
Wed Jun 15 10:26:42 CDT 2011


# HG changeset patch
# User Pierre-Yves David <pierre-yves.david at logilab.fr>
# Date 1308147106 -7200
# Node ID 41c67cd46f8335731d347c9cf211d752e9ee1939
# Parent  57e274bf5a792646ca7f8a09aabd4c4faaa686e7
hidden: optimise hidden set computation

We remember revision we failed to hide. When receving a new request to hide
changeset, we only evaluate those who previously failed and the new revs.

diff --git a/mercurial/changelog.py b/mercurial/changelog.py
--- a/mercurial/changelog.py
+++ b/mercurial/changelog.py
@@ -105,12 +105,13 @@ class changelog(revlog.revlog):
             self.version &= ~revlog.REVLOGGENERALDELTA
             self._generaldelta = False
         self._realopener = opener
         self._delayed = False
         self._divert = False
-        self._hidden = set()
-        self._hidable = set()
+        self._hidable = set()  # rev we want to hide
+        self._hidden = set()   # rev we managed to hide
+        self._revealed = set() # rev we failed to hide
 
     def hidden(self, rev):
         """Is rev hidden?"""
         return rev in self._hidden
 
@@ -118,36 +119,41 @@ class changelog(revlog.revlog):
         """Request to hide a revision,
 
         The request won't take effect until all children are hidden too.
         """
         self._hidable.add(rev)
-        self._refreshhidden()
+        self._refreshhidden(newrevs=(rev,))
 
-    def _refreshhidden(self):
+    def _refreshhidden(self, newrevs=None):
         """Recompute the set of hidden revision
 
         A revision is hidden if both:
             * He is in the hidable,
             * all it's descendant are also hidable."""
-
-        self._hidden.clear()
+        if newrevs is None:
+            self._hidden.clear()
+            candidates = set(self._hidable)
+        else:
+            candidates = set(self._revealed)
+            candidates.update(newrevs)
         # all nodes known to be shown
         shown = set()
-        candidates = set(self._hidable)
         # iterate in reverse topological order to make sure children of X
         # are resolved before we evalute X
-        for cand in sorted(self._hidable, reverse=True):
+        for cand in sorted(candidates, reverse=True):
             # self.children take node ...
             node = self.node(cand)
             for childnode in self.children(node):
                 # self.children return node ...
                 child = self.rev(childnode)
-                if child in shown or child not in candidates:
+                if child in shown or child not in self._hidable:
                     shown.update((cand, child))
                     break
             else: # if no break
                 self._hidden.add(cand)
+        # cache those who failed to only wheck them next time.
+        self._revealed = shown & self._hidable
 
     def delayupdate(self):
         "delay visibility of index updates to other readers"
         self._delayed = True
         self._divert = (len(self) == 0)


More information about the Mercurial-devel mailing list