# HG changeset patch # User Yuya Nishihara # Date 2018-10-12 04:22:43 # Node ID adbf8ca239e458d8a18aae5a5dc12f8fa030521c # Parent 38ac525b44c93fcadb3680d4ded56f1e5a0029b2 revlog: optimize ancestors() to not check filtered revisions for each While reviewing the Rust implementation, I noticed iter(ancestors) doesn't need to check filtering state for each parent revision. And doing that appears to have some measurable perf win. $ hg perfancestors -R mercurial (orig) wall 0.038093 comb 0.040000 user 0.040000 sys 0.000000 (best of 100) (this) wall 0.024795 comb 0.020000 user 0.020000 sys 0.000000 (best of 117) diff --git a/mercurial/revlog.py b/mercurial/revlog.py --- a/mercurial/revlog.py +++ b/mercurial/revlog.py @@ -648,6 +648,9 @@ class revlog(object): return entry[5], entry[6] + # fast parentrevs(rev) where rev isn't filtered + _uncheckedparentrevs = parentrevs + def node(self, rev): try: return self.index[rev][7] @@ -747,8 +750,14 @@ class revlog(object): See the documentation for ancestor.lazyancestors for more details.""" - return ancestor.lazyancestors(self.parentrevs, revs, stoprev=stoprev, - inclusive=inclusive) + # first, make sure start revisions aren't filtered + revs = list(revs) + checkrev = self.node + for r in revs: + checkrev(r) + # and we're sure ancestors aren't filtered as well + return ancestor.lazyancestors(self._uncheckedparentrevs, revs, + stoprev=stoprev, inclusive=inclusive) def descendants(self, revs): return dagop.descendantrevs(revs, self.revs, self.parentrevs)