topic: instroduce a fast path when computing stack stable
authorPierre-Yves David <pierre-yves.david@octobus.net>
Mon, 23 Oct 2017 15:11:48 +0200
branchstable
changeset 3123 237b39bf7e6b
parent 3115 663dbef40f97
child 3124 6ef274e01f64
topic: instroduce a fast path when computing stack We do some stack related computation during transaction now. The current inefficiency of the revset is hurting us too much. We pre-compute a subset using native set operation to speed things up.
hgext3rd/topic/stack.py
--- a/hgext3rd/topic/stack.py	Fri Oct 20 22:44:12 2017 +0200
+++ b/hgext3rd/topic/stack.py	Mon Oct 23 15:11:48 2017 +0200
@@ -9,6 +9,7 @@
     error,
     node,
     phases,
+    obsolete,
     util,
 )
 from .evolvebits import builddependencies, _singlesuccessor
@@ -23,6 +24,25 @@
 if not util.safehasattr(context.basectx, 'isunstable'):
     context.basectx.isunstable = context.basectx.troubled
 
+def _stackcandidates(repo):
+    """build the smaller set of revs that might be part of a stack.
+
+    The intend is to build something more efficient than what revsets do in
+    this area.
+    """
+    phasecache = repo._phasecache
+    if not phasecache._phasesets:
+        return repo.revs('(not public()) - obsolete()')
+    if any(s is None for s in phasecache._phasesets):
+        return repo.revs('(not public()) - obsolete()')
+
+    result = set()
+    for s in phasecache._phasesets[phases.draft:]:
+        result |= s
+
+    result -= obsolete.getrevs(repo, 'obsolete')
+    return result
+
 class stack(object):
     """object represent a stack and common logic associated to it."""
 
@@ -31,12 +51,15 @@
         self.branch = branch
         self.topic = topic
         self.behinderror = None
+
+        subset = _stackcandidates(repo)
+
         if topic is not None and branch is not None:
             raise error.ProgrammingError('both branch and topic specified (not defined yet)')
         elif topic is not None:
-            trevs = repo.revs("not obsolete() and topic(%s)", topic)
+            trevs = repo.revs("%ld and topic(%s)", subset, topic)
         elif branch is not None:
-            trevs = repo.revs("not public() and branch(%s) - obsolete() - topic()", branch)
+            trevs = repo.revs("%ld and branch(%s) - topic()", subset, branch)
         else:
             raise error.ProgrammingError('neither branch and topic specified (not defined yet)')
         self._revs = trevs