revset: make descendants() lazier
Previously descendants() would force the provided subset to become a set. In
the case of revsets like '(%ld::) - (%ld)' (as used by histedit) this would
force the '- (%ld)' set to be evaluated, which produced a set containing every
commit in the repo (except %ld). This takes 0.6s on large repos.
This changes descendants to trust the subset to implement __contains__
efficiently, which improves the above revset to 0.16s. Shaving 0.4 seconds off
of histedit.
revset #27: (20000::) - (20000)
0) obsolete feature not enabled but 54243 markers found!
! wall 0.023640 comb 0.020000 user 0.020000 sys 0.000000 (best of 100)
1) obsolete feature not enabled but 54243 markers found!
! wall 0.019589 comb 0.020000 user 0.020000 sys 0.000000 (best of 100)
This commit removes the final revset related perf hotspot from histedit.
Combined with the previous two patches, they shave a little over 3 seconds off
histedit on large repos.
--- a/contrib/revsetbenchmarks.txt Wed Sep 17 00:28:37 2014 +0900
+++ b/contrib/revsetbenchmarks.txt Fri Sep 12 16:21:13 2014 -0700
@@ -23,3 +23,4 @@
max(::(tip~20) - obsolete())
roots((0:tip)::)
(not public() - obsolete())
+(20000::) - (20000)
--- a/mercurial/revset.py Wed Sep 17 00:28:37 2014 +0900
+++ b/mercurial/revset.py Fri Sep 12 16:21:13 2014 -0700
@@ -666,10 +666,8 @@
# Both sets need to be ascending in order to lazily return the union
# in the correct order.
args.ascending()
-
- subsetset = subset.set()
- result = (orderedlazyset(s, subsetset.__contains__, ascending=True) +
- orderedlazyset(args, subsetset.__contains__, ascending=True))
+ result = (orderedlazyset(s, subset.__contains__, ascending=True) +
+ orderedlazyset(args, subset.__contains__, ascending=True))
# Wrap result in a lazyset since it's an _addset, which doesn't implement
# all the necessary functions to be consumed by callers.