From patchwork Wed Oct 3 19:10:49 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [6, of, 8, V3] context: floor adjustlinkrev graph walk during copy tracing From: Boris Feld X-Patchwork-Id: 35421 Message-Id: To: mercurial-devel@mercurial-scm.org Cc: gregory.szorc@gmail.com Date: Wed, 03 Oct 2018 21:10:49 +0200 # HG changeset patch # User Boris Feld # Date 1536255188 14400 # Thu Sep 06 13:33:08 2018 -0400 # Node ID fd0da35824d09d0a0fa66a23627dd24209c6c3b1 # Parent 964fbe39ab182eb0d65830dc87ef39d0382a41fa # EXP-Topic copy-perf # Available At https://bitbucket.org/octobus/mercurial-devel/ # hg pull https://bitbucket.org/octobus/mercurial-devel/ -r fd0da35824d0 context: floor adjustlinkrev graph walk during copy tracing The `_adjustlinkrev` method gains an optional "stoprev" argument. The linkrev adjustment will give up once this floor is reached. The relevant functions using `_adjustlinkrev` are updated to pass an appropriate value in the copy tracing code. In some private repository, about 10% of the status call triggered pathological case addressed by this change. The speedup varies from one call to another, the best-observed win is moving from 170s to 11s. diff --git a/mercurial/context.py b/mercurial/context.py --- a/mercurial/context.py +++ b/mercurial/context.py @@ -569,7 +569,7 @@ class basefilectx(object): def _changeid(self): return self._findchangerev() - def _findchangerev(self): + def _findchangerev(self, stoprev=None): if r'_changeid' in self.__dict__: changeid = self._changeid elif r'_changectx' in self.__dict__: @@ -577,10 +577,11 @@ class basefilectx(object): elif r'_descendantrev' in self.__dict__: # this file context was created from a revision with a known # descendant, we can (lazily) correct for linkrev aliases - changeid = self._adjustlinkrev(self._descendantrev) + changeid = self._adjustlinkrev(self._descendantrev, stoprev=stoprev) else: changeid = self._filelog.linkrev(self._filerev) - self._changeid = changeid + if changeid is not None: + self._changeid = changeid return changeid @propertycache @@ -724,7 +725,7 @@ class basefilectx(object): return True - def _adjustlinkrev(self, srcrev, inclusive=False): + def _adjustlinkrev(self, srcrev, inclusive=False, stoprev=None): """return the first ancestor of introducing If the linkrev of the file revision does not point to an ancestor of @@ -733,6 +734,10 @@ class basefilectx(object): :srcrev: the changeset revision we search ancestors from :inclusive: if true, the src revision will also be checked + :stoprev: an optional revision to stop the walk at. If no introduction + of this file content could be found before this floor + revision, the function will returns "None" and stops its + iteration. """ repo = self._repo cl = repo.unfiltered().changelog @@ -758,6 +763,8 @@ class basefilectx(object): fnode = self._filenode path = self._path for a in iteranc: + if stoprev is not None and a < stoprev: + return None ac = cl.read(a) # get changeset data (we avoid object creation) if path in ac[3]: # checking the 'files' field. # The file has been touched, check if the content is @@ -773,8 +780,12 @@ class basefilectx(object): def isintroducedafter(self, changelogrev): """True if a filectx have been introduced after a given floor revision """ - return (changelogrev <= self.linkrev() - or changelogrev <= self._introrev()) + if changelogrev <= self.linkrev(): + return True + introrev = self._introrev(stoprev=changelogrev) + if introrev is None: + return False + return changelogrev <= introrev def _lazyrevavailable(self): """return True if self.rev() is available without computation, @@ -804,7 +815,15 @@ class basefilectx(object): """ return self._introrev() - def _introrev(self): + def _introrev(self, stoprev=None): + """ + Same as `introrev` but, with an extra argument to limit changelog + iteration range in some internal usecase. + + If `stoprev` is set, the `introrev` will not be searched past that + `stoprev` revision and "None" might be returned. This is useful to + limit iteration range. + """ lkr = self.linkrev() attrs = vars(self) lazyavailable = self._lazyrevavailable() @@ -813,9 +832,10 @@ class basefilectx(object): if rev == lkr: return rev else: - return self._adjustlinkrev(rev, inclusive=True) + return self._adjustlinkrev(rev, inclusive=True, + stoprev=stoprev) else: - return self._findchangerev() + return self._findchangerev(stoprev=stoprev) def introfilectx(self): """Return filectx having identical contents, but pointing to the