revset: use phasecache.getrevset
This is part of a refactoring that moves some phase query optimization from
revset.py to phases.py. See the previous patch for motivation.
This patch changes revset code to use phasecache.getrevset so it no longer
accesses the private field: _phasecache._phasesets directly.
For performance impact, this patch was tested using the following query, on
my hg-committed repo:
for i in 'public()' 'not public()' 'draft()' 'not draft()'; do
echo $i;
hg perfrevset "$i";
hg perfrevset "$i" --hidden;
done
For the CPython implementation, most operations are unchanged (within
+/- 1%), while "not public()" and "draft()" is noticeably faster on an
unfiltered repo. It may be because the new code avoids a set copy if
filteredrevs is empty.
revset | public() | not public() | draft() | not draft()
hidden | yes | no | yes | no | yes | no | yes | no
------------------------------------------------------------------
before | 19006 | 17352 | 239 | 286 | 180 | 228 | 7690 | 5745
after | 19137 | 17231 | 240 | 207 | 182 | 150 | 7687 | 5658
delta | | -38% | | -52% |
(timed in microseconds)
For the pure Python implementation, some operations are faster while "not
draft()" is noticeably slower:
revset | public() | not public() | draft() | not draft()
hidden | yes | no | yes | no | yes | no | yes | no
------------------------------------------------------------------------
before | 18852 | 17183 | 17758 | 15921 | 17505 | 15973 | 41521 | 39822
after | 18924 | 17380 | 17558 | 14545 | 16727 | 13593 | 48356 | 43992
delta | | -9% | -5% | -15% | +16% | +10%
That may be the different performance characters of generatorset vs.
filteredset. The "not draft()" query could be optimized in this case where
both "public" and "secret" are passed to "getrevsets" so it won't iterate
the whole repo twice.
--- a/mercurial/revset.py Fri Feb 17 22:49:05 2017 -0800
+++ b/mercurial/revset.py Sat Feb 18 00:39:31 2017 -0800
@@ -1644,19 +1644,10 @@
ps -= set([node.nullrev])
return subset & ps
-def _phase(repo, subset, target):
- """helper to select all rev in phase <target>"""
- repo._phasecache.loadphaserevs(repo) # ensure phase's sets are loaded
- if repo._phasecache._phasesets:
- s = repo._phasecache._phasesets[target] - repo.changelog.filteredrevs
- s = baseset(s)
- s.sort() # set are non ordered, so we enforce ascending
- return subset & s
- else:
- phase = repo._phasecache.phase
- condition = lambda r: phase(repo, r) == target
- return subset.filter(condition, condrepr=('<phase %r>', target),
- cache=False)
+def _phase(repo, subset, *targets):
+ """helper to select all rev in <targets> phases"""
+ s = repo._phasecache.getrevset(repo, targets)
+ return subset & s
@predicate('draft()', safe=True)
def draft(repo, subset, x):
@@ -1717,20 +1708,7 @@
@predicate('_notpublic', safe=True)
def _notpublic(repo, subset, x):
getargs(x, 0, 0, "_notpublic takes no arguments")
- repo._phasecache.loadphaserevs(repo) # ensure phase's sets are loaded
- if repo._phasecache._phasesets:
- s = set()
- for u in repo._phasecache._phasesets[1:]:
- s.update(u)
- s = baseset(s - repo.changelog.filteredrevs)
- s.sort()
- return subset & s
- else:
- phase = repo._phasecache.phase
- target = phases.public
- condition = lambda r: phase(repo, r) != target
- return subset.filter(condition, condrepr=('<phase %r>', target),
- cache=False)
+ return _phase(repo, subset, phases.draft, phases.secret)
@predicate('public()', safe=True)
def public(repo, subset, x):