[PATCH 2 of 2] push: restrict common discovery to the pushed set

Boris Feld boris.feld at octobus.net
Thu Dec 7 07:32:13 EST 2017


# HG changeset patch
# User Boris Feld <boris.feld at octobus.net>
# Date 1512599581 -3600
#      Wed Dec 06 23:33:01 2017 +0100
# Node ID eeed65db2847b39998c8a08cfa4e44ec8381b2e9
# Parent  f2fcdbfa1475d055caaa44c9cc23a58284c97e4b
# EXP-Topic discovery
# Available At https://bitbucket.org/octobus/mercurial-devel/
#              hg pull https://bitbucket.org/octobus/mercurial-devel/ -r eeed65db2847
push: restrict common discovery to the pushed set

This changeset make use of the ability of the set discovery to only search
common changeset for a subset of the repository. Restricting that search to the
pushed set avoid potential waste of time finding out the status of many
unrelated related revision.

Repository with many heads were especially badly affected by this. Here is an
example of findcommonhead discovery for pushing 11 outgoing changeset on a
repository with tens of thousand of unrelated heads. (discovery run over a ssh
link to localhost).

Before:
    queries: 92
    time:    44.1996s

After:
    queries: 3
    time:    0.6938s

A x63 speedup even with a network link without latency.

diff --git a/mercurial/discovery.py b/mercurial/discovery.py
--- a/mercurial/discovery.py
+++ b/mercurial/discovery.py
@@ -27,7 +27,7 @@ from . import (
     util,
 )
 
-def findcommonincoming(repo, remote, heads=None, force=False):
+def findcommonincoming(repo, remote, heads=None, force=False, ancestorsof=None):
     """Return a tuple (common, anyincoming, heads) used to identify the common
     subset of nodes between repo and remote.
 
@@ -38,6 +38,9 @@ def findcommonincoming(repo, remote, hea
       changegroupsubset. No code except for pull should be relying on this fact
       any longer.
     "heads" is either the supplied heads, or else the remote's heads.
+    "ancestorsof" if not None, restrict the discovery to a subset defined by
+      these nodes. Changeset outside of this set won't be considered (and
+      won't appears in "common")
 
     If you pass heads and they are all known locally, the response lists just
     these heads in "common" and in "heads".
@@ -60,7 +63,8 @@ def findcommonincoming(repo, remote, hea
             return (heads, False, heads)
 
     res = setdiscovery.findcommonheads(repo.ui, repo, remote,
-                                       abortwhenunrelated=not force)
+                                       abortwhenunrelated=not force,
+                                       ancestorsof=ancestorsof)
     common, anyinc, srvheads = res
     return (list(common), anyinc, heads or list(srvheads))
 
@@ -142,7 +146,8 @@ def findcommonoutgoing(repo, other, only
 
     # get common set if not provided
     if commoninc is None:
-        commoninc = findcommonincoming(repo, other, force=force)
+        commoninc = findcommonincoming(repo, other, force=force,
+                                       ancestorsof=onlyheads)
     og.commonheads, _any, _hds = commoninc
 
     # compute outgoing
diff --git a/mercurial/exchange.py b/mercurial/exchange.py
--- a/mercurial/exchange.py
+++ b/mercurial/exchange.py
@@ -512,7 +512,11 @@ def _pushdiscovery(pushop):
 def _pushdiscoverychangeset(pushop):
     """discover the changeset that need to be pushed"""
     fci = discovery.findcommonincoming
-    commoninc = fci(pushop.repo, pushop.remote, force=pushop.force)
+    if pushop.revs:
+        commoninc = fci(pushop.repo, pushop.remote, force=pushop.force,
+                        ancestorsof=pushop.revs)
+    else:
+        commoninc = fci(pushop.repo, pushop.remote, force=pushop.force)
     common, inc, remoteheads = commoninc
     fco = discovery.findcommonoutgoing
     outgoing = fco(pushop.repo, pushop.remote, onlyheads=pushop.revs,


More information about the Mercurial-devel mailing list