exchange: improve computation of relevant markers for large repos
authorJoerg Sonnenberger <joerg@bec.de>
Tue, 11 Jun 2024 18:47:50 +0200
changeset 51644 f28c52a9f7b4
parent 51642 69c5f8d6c710
child 51645 ff523675cd69
exchange: improve computation of relevant markers for large repos Find the candidates for nodes with relevant markers by going over all markers instead of iterating over all nodes. Most nodes will not have markers anyway. Further optimize the code by allowing revsets as well, which reduces the materialization cost.
mercurial/bundle2.py
mercurial/exchange.py
mercurial/obsolete.py
mercurial/obsutil.py
--- a/mercurial/bundle2.py	Wed Jun 12 11:29:11 2024 +0200
+++ b/mercurial/bundle2.py	Tue Jun 11 18:47:50 2024 +0200
@@ -1788,7 +1788,7 @@
         addpartrevbranchcache(repo, bundler, outgoing)
 
     if opts.get(b'obsolescence', False):
-        obsmarkers = repo.obsstore.relevantmarkers(outgoing.missing)
+        obsmarkers = repo.obsstore.relevantmarkers(nodes=outgoing.missing)
         buildobsmarkerspart(
             bundler,
             obsmarkers,
--- a/mercurial/exchange.py	Wed Jun 12 11:29:11 2024 +0200
+++ b/mercurial/exchange.py	Tue Jun 11 18:47:50 2024 +0200
@@ -703,8 +703,8 @@
     repo = pushop.repo
     # very naive computation, that can be quite expensive on big repo.
     # However: evolution is currently slow on them anyway.
-    nodes = (c.node() for c in repo.set(b'::%ln', pushop.futureheads))
-    pushop.outobsmarkers = pushop.repo.obsstore.relevantmarkers(nodes)
+    revs = repo.revs(b'::%ln', pushop.futureheads)
+    pushop.outobsmarkers = pushop.repo.obsstore.relevantmarkers(revs=revs)
 
 
 @pushdiscovery(b'bookmarks')
@@ -2605,8 +2605,8 @@
     if kwargs.get('obsmarkers', False):
         if heads is None:
             heads = repo.heads()
-        subset = [c.node() for c in repo.set(b'::%ln', heads)]
-        markers = repo.obsstore.relevantmarkers(subset)
+        revs = repo.revs(b'::%ln', heads)
+        markers = repo.obsstore.relevantmarkers(revs=revs)
         markers = obsutil.sortedmarkers(markers)
         bundle2.buildobsmarkerspart(bundler, markers)
 
--- a/mercurial/obsolete.py	Wed Jun 12 11:29:11 2024 +0200
+++ b/mercurial/obsolete.py	Tue Jun 11 18:47:50 2024 +0200
@@ -771,10 +771,11 @@
             _addchildren(self.children, markers)
         _checkinvalidmarkers(self.repo, markers)
 
-    def relevantmarkers(self, nodes):
-        """return a set of all obsolescence markers relevant to a set of nodes.
+    def relevantmarkers(self, nodes=None, revs=None):
+        """return a set of all obsolescence markers relevant to a set of
+        nodes or revisions.
 
-        "relevant" to a set of nodes mean:
+        "relevant" to a set of nodes or revisions mean:
 
         - marker that use this changeset as successor
         - prune marker of direct children on this changeset
@@ -782,10 +783,24 @@
           markers
 
         It is a set so you cannot rely on order."""
+        if nodes is None:
+            nodes = set()
+        if revs is None:
+            revs = set()
 
-        pendingnodes = set(nodes)
+        get_rev = self.repo.unfiltered().changelog.index.get_rev
+        pendingnodes = set()
+        for marker in self._all:
+            for node in (marker[0],) + marker[1] + (marker[5] or ()):
+                if node in nodes:
+                    pendingnodes.add(node)
+                elif revs:
+                    rev = get_rev(node)
+                    if rev is not None and rev in revs:
+                        pendingnodes.add(node)
         seenmarkers = set()
-        seennodes = set(pendingnodes)
+        seenmarkers = set()
+        seennodes = set()
         precursorsmarkers = self.predecessors
         succsmarkers = self.successors
         children = self.children
--- a/mercurial/obsutil.py	Wed Jun 12 11:29:11 2024 +0200
+++ b/mercurial/obsutil.py	Tue Jun 11 18:47:50 2024 +0200
@@ -108,7 +108,7 @@
     elif exclusive:
         rawmarkers = exclusivemarkers(repo, nodes)
     else:
-        rawmarkers = repo.obsstore.relevantmarkers(nodes)
+        rawmarkers = repo.obsstore.relevantmarkers(nodes=nodes)
 
     for markerdata in rawmarkers:
         yield marker(repo, markerdata)