revset: make use of natively-computed set for 'draft()' and 'secret()'
authorPierre-Yves David <pierre-yves.david@fb.com>
Wed, 10 Jun 2015 19:18:51 -0700
changeset 25622 85294076adce
parent 25621 21a874693619
child 25623 0bee97fa1fa8
revset: make use of natively-computed set for 'draft()' and 'secret()' If the computation of a set for each phase (done in C) is available, we use it directly instead of applying a simple filter. This give a massive speed-up in the vast majority of cases. On my mercurial repo with about 15000 out of 40000 draft changesets: revset: draft() plain min first last 0) 0.011201 0.019950 0.009844 0.000074 1) 0.000284 2% 0.000312 1% 0.000314 3% 0.000315 x4.3 Bad performance for "last" come from the handling of the 15000 elements set (memory allocation, filtering hidden changesets (99% of it) etc. compared to applying the filter only on a handfuld of revisions (the first draft changesets being close of tip). This is not seen as an issue since: * Timing is still pretty good and in line with all the other one, * Current user of Vanilla Mercurial will not have 1/3 of their repo draft, This bad effect disappears when phase's set is smaller. (about 200 secrets): revset: secret() plain min first last 0) 0.011181 0.022228 0.010851 0.000452 1) 0.000058 0% 0.000084 0% 0.000087 0% 0.000087 19%
contrib/all-revsets.txt
mercurial/revset.py
--- a/contrib/all-revsets.txt	Wed Jun 17 19:19:57 2015 -0700
+++ b/contrib/all-revsets.txt	Wed Jun 10 19:18:51 2015 -0700
@@ -124,3 +124,7 @@
 head() - public()
 draft() and head()
 head() and author("mpm")
+
+# testing the mutable phases set
+draft()
+secret()
--- a/mercurial/revset.py	Wed Jun 17 19:19:57 2015 -0700
+++ b/mercurial/revset.py	Wed Jun 10 19:18:51 2015 -0700
@@ -1464,9 +1464,16 @@
 
 def _phase(repo, subset, target):
     """helper to select all rev in phase <target>"""
-    phase = repo._phasecache.phase
-    condition = lambda r: phase(repo, r) == target
-    return subset.filter(condition, cache=False)
+    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, cache=False)
 
 def draft(repo, subset, x):
     """``draft()``