##// END OF EJS Templates
rust-dirstatemap: don't read the dirstate when requesting parents...
rust-dirstatemap: don't read the dirstate when requesting parents A future patch for issue 6303 reveals a big performance regression in the Rust `DirstateMap` that reads the entire dirstate when requesting parents instead of the first 40 bytes. `perfdiscovery` gets a *significant* speedup (from 0.101 to 0.016) when applied against said patch. I'm assuming it has other performance benefits, but this is already a good enough win. Differential Revision: https://phab.mercurial-scm.org/D8513

File last commit:

r43347:687b865b default
r45358:18e36ff8 stable
Show More
treediscovery.py
182 lines | 5.7 KiB | text/x-python | PythonLexer
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 # discovery.py - protocol changeset discovery functions
#
# Copyright 2010 Matt Mackall <mpm@selenic.com>
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
Gregory Szorc
treediscovery: use absolute_import
r25987 from __future__ import absolute_import
Martin von Zweigbergk
util: drop alias for collections.deque...
r25113 import collections
Gregory Szorc
treediscovery: use absolute_import
r25987
from .i18n import _
from .node import (
nullid,
short,
)
from . import (
error,
Gregory Szorc
global: use pycompat.xrange()...
r38806 pycompat,
Gregory Szorc
treediscovery: use absolute_import
r25987 )
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164
Augie Fackler
formatting: blacken the codebase...
r43346
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 def findcommonincoming(repo, remote, heads=None, force=False):
"""Return a tuple (common, fetch, heads) used to identify the common
subset of nodes between repo and remote.
"common" is a list of (at least) the heads of the common subset.
"fetch" is a list of roots of the nodes that would be incoming, to be
supplied to changegroupsubset.
"heads" is either the supplied heads, or else the remote's heads.
"""
Pierre-Yves David
discovery: stop using nodemap for membership testing...
r20225 knownnode = repo.changelog.hasnode
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 search = []
fetch = set()
seen = set()
seenbranch = set()
base = set()
if not heads:
Gregory Szorc
treediscovery: switch to command executor interface...
r37652 with remote.commandexecutor() as e:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 heads = e.callcommand(b'heads', {}).result()
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164
if repo.changelog.tip() == nullid:
base.add(nullid)
if heads != [nullid]:
return [nullid], [nullid], list(heads)
Peter Arrenbrecht
treediscovery: fix regression when run against older repos (issue2793)...
r14199 return [nullid], [], heads
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164
# assume we're closer to the tip than the root
# and start by examining the heads
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.status(_(b"searching for changes\n"))
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164
unknown = []
for h in heads:
Pierre-Yves David
discovery: stop using nodemap for membership testing...
r20225 if not knownnode(h):
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 unknown.append(h)
else:
base.add(h)
Peter Arrenbrecht
treediscovery: fix regression when run against older repos (issue2793)...
r14199 if not unknown:
return list(base), [], list(heads)
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 req = set(unknown)
reqcnt = 0
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 progress = repo.ui.makeprogress(_(b'searching'), unit=_(b'queries'))
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164
# search through remote branches
# a 'branch' here is a linear segment of history, with four parts:
# head, root, first parent, second parent
# (a branch always has two parents (or none) by definition)
Gregory Szorc
treediscovery: switch to command executor interface...
r37652 with remote.commandexecutor() as e:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 branches = e.callcommand(b'branches', {b'nodes': unknown}).result()
Gregory Szorc
treediscovery: switch to command executor interface...
r37652
unknown = collections.deque(branches)
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 while unknown:
r = []
while unknown:
Bryan O'Sullivan
cleanup: use the deque type where appropriate...
r16803 n = unknown.popleft()
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 if n[0] in seen:
continue
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.debug(b"examining %s:%s\n" % (short(n[0]), short(n[1])))
Augie Fackler
formatting: blacken the codebase...
r43346 if n[0] == nullid: # found the end of the branch
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 pass
elif n in seenbranch:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.debug(b"branch already found\n")
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 continue
Augie Fackler
formatting: blacken the codebase...
r43346 elif n[1] and knownnode(n[1]): # do we know the base?
repo.ui.debug(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"found incomplete branch %s:%s\n"
Augie Fackler
formatting: blacken the codebase...
r43346 % (short(n[0]), short(n[1]))
)
search.append(n[0:2]) # schedule branch range for scanning
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 seenbranch.add(n)
else:
if n[1] not in seen and n[1] not in fetch:
Pierre-Yves David
discovery: stop using nodemap for membership testing...
r20225 if knownnode(n[2]) and knownnode(n[3]):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.debug(b"found new changeset %s\n" % short(n[1]))
Augie Fackler
formatting: blacken the codebase...
r43346 fetch.add(n[1]) # earliest unknown
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 for p in n[2:4]:
Pierre-Yves David
discovery: stop using nodemap for membership testing...
r20225 if knownnode(p):
Augie Fackler
formatting: blacken the codebase...
r43346 base.add(p) # latest known
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164
for p in n[2:4]:
Pierre-Yves David
discovery: stop using nodemap for membership testing...
r20225 if p not in req and not knownnode(p):
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 r.append(p)
req.add(p)
seen.add(n[0])
if r:
reqcnt += 1
Martin von Zweigbergk
treediscovery: use progress helper...
r38419 progress.increment()
Augie Fackler
formatting: blacken the codebase...
r43346 repo.ui.debug(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"request %d: %s\n" % (reqcnt, b" ".join(map(short, r)))
Augie Fackler
formatting: blacken the codebase...
r43346 )
Gregory Szorc
global: use pycompat.xrange()...
r38806 for p in pycompat.xrange(0, len(r), 10):
Gregory Szorc
treediscovery: switch to command executor interface...
r37652 with remote.commandexecutor() as e:
Augie Fackler
formatting: blacken the codebase...
r43346 branches = e.callcommand(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'branches', {b'nodes': r[p : p + 10],}
Augie Fackler
formatting: blacken the codebase...
r43346 ).result()
Gregory Szorc
treediscovery: switch to command executor interface...
r37652
for b in branches:
Augie Fackler
formatting: blacken the codebase...
r43346 repo.ui.debug(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"received %s:%s\n" % (short(b[0]), short(b[1]))
Augie Fackler
formatting: blacken the codebase...
r43346 )
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 unknown.append(b)
# do binary search on the branches we found
while search:
newsearch = []
reqcnt += 1
Martin von Zweigbergk
treediscovery: use progress helper...
r38419 progress.increment()
Gregory Szorc
treediscovery: switch to command executor interface...
r37652
with remote.commandexecutor() as e:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 between = e.callcommand(b'between', {b'pairs': search}).result()
Gregory Szorc
treediscovery: switch to command executor interface...
r37652
for n, l in zip(search, between):
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 l.append(n[1])
p = n[0]
f = 1
for i in l:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.debug(b"narrowing %d:%d %s\n" % (f, len(l), short(i)))
Pierre-Yves David
discovery: stop using nodemap for membership testing...
r20225 if knownnode(i):
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 if f <= 2:
Augie Fackler
formatting: blacken the codebase...
r43346 repo.ui.debug(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"found new branch changeset %s\n" % short(p)
Augie Fackler
formatting: blacken the codebase...
r43346 )
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 fetch.add(p)
base.add(i)
else:
Augie Fackler
formatting: blacken the codebase...
r43346 repo.ui.debug(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"narrowed branch search to %s:%s\n"
Augie Fackler
formatting: blacken the codebase...
r43346 % (short(p), short(i))
)
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 newsearch.append((p, i))
break
p, f = i, f * 2
search = newsearch
# sanity check our fetch list
for f in fetch:
Pierre-Yves David
discovery: stop using nodemap for membership testing...
r20225 if knownnode(f):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.RepoError(_(b"already have changeset ") + short(f[:4]))
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164
base = list(base)
if base == [nullid]:
if force:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.warn(_(b"warning: repository is unrelated\n"))
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b"repository is unrelated"))
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164
Augie Fackler
formatting: blacken the codebase...
r43346 repo.ui.debug(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"found new changesets starting at "
+ b" ".join([short(f) for f in fetch])
+ b"\n"
Augie Fackler
formatting: blacken the codebase...
r43346 )
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164
Martin von Zweigbergk
treediscovery: use progress helper...
r38419 progress.complete()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.debug(b"%d total queries\n" % reqcnt)
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164
return base, list(fetch), heads