# HG changeset patch # User Boris Feld <boris.f...@octobus.net> # Date 1536252767 14400 # Thu Sep 06 12:52:47 2018 -0400 # Node ID a7dba588d74f3d71c988b9a89b9591fb530a1d14 # Parent a4c3eb6c1a36cbbf64fa8930b173154b2e77ef2b # EXP-Topic copy-perf # Available At https://bitbucket.org/octobus/mercurial-devel/ # hg pull https://bitbucket.org/octobus/mercurial-devel/ -r a7dba588d74f context: introduce an `isintroducedafter` method and use it in copies
Right now, copy tracing make effort to not traverse the graph too much to save performance. It uses a "limit" acting as a floor revision past which data are no longer relevant to the current copy tracing. However, to enforce this limit, it uses a call to `filectx.rev()`, that call can trigger a graph traversal on its own. That extra graph traversal is oblivious of the current limit and can become very expensive. That cost is increased by the nature of work done in adjust link rev, we are not only walking down the graph, we are also checking the affected file for each revision we walk through. Something significantly more expensive than the walk itself. To work around this we need to make the `filectx` operation aware of the current limit. The first step is to introduce a dedicated method: `isintroducedafter`. We'll then rework that method logic to stop traversal as soon as possible. diff --git a/mercurial/context.py b/mercurial/context.py --- a/mercurial/context.py +++ b/mercurial/context.py @@ -829,6 +829,12 @@ class basefilectx(object): # result is crash somewhere else at to some point. return lkr + def isintroducedafter(self, changelogrev): + """True if a filectx have been introduced after a given floor revision + """ + return (changelogrev <= self.linkrev() + or changelogrev <= self.introrev()) + def _lazyrev(self): """return self.rev() if it is available without computation, diff --git a/mercurial/copies.py b/mercurial/copies.py --- a/mercurial/copies.py +++ b/mercurial/copies.py @@ -139,7 +139,7 @@ def _tracefile(fctx, am, limit=-1): for f in fctx.ancestors(): if am.get(f.path(), None) == f.filenode(): return f - if limit >= 0 and f.linkrev() < limit and f.rev() < limit: + if limit >= 0 and not f.isintroducedafter(limit): return None def _dirstatecopies(d, match=None): _______________________________________________ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel