# HG changeset patch # User Boris Feld # Date 2017-12-06 22:33:01 # Node ID 483b5dd0f1aa412e9611ab694279c9d3735fee99 # Parent f77121b6bf1b66b6f3cf6d7a665e2907577d1717 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 @@ -514,7 +514,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,