Mercurial > hg
changeset 28217:d2ac8b57a75d
revset: use smartset minus operator
Previously, revsets like 'X - Y' were translated to be 'X and not Y'. This can
be expensive, since if Y is a single commit then 'not Y' becomes a huge set and
sometimes the query optimizer doesn't account for it well.
This patch changes revsets to use the built in smartset minus operator, which is
often smarter than 'X and not Y'.
On a large repo this saves 2.2 seconds on rebase and histedit because "X:: - X"
becomes almost instant.
Relevant performance numbers from revsetbenchmark.py
revset #13: roots((tip~100::) - (tip~100::tip))
plain min max first last reverse rev..rst rev..ast sort sor..rst sor..ast
0) 0.001080 0.001107 0.001102 0.001118 0.001121 0.001114 0.001141 0.001123 0.001099 0.001123 0.001137
1) 0.000708 65% 0.000738 66% 0.000735 66% 0.000739 66% 0.000784 69% 0.000780 70% 0.000807 70% 0.000756 67% 0.000727 66% 0.000759 67% 0.000808 71%
revset #14: roots((0::) - (0::tip))
plain min max first last reverse rev..rst rev..ast sort sor..rst sor..ast
0) 0.131304 0.079168 0.133129 0.076560 0.048179 0.133349 0.049153 0.077097 0.129689 0.076212 0.048543
1) 0.065066 49% 0.036941 46% 0.066063 49% 0.034755 45% 0.048558 0.071091 53% 0.047679 0.034984 45% 0.064572 49% 0.035680 46% 0.048508
revset #22: (not public() - obsolete())
plain min max first last reverse rev..rst rev..ast sort sor..rst sor..ast
0) 0.000139 0.000133 0.000133 0.000138 0.000134 0.000155 0.000157 0.000152 0.000157 0.000156 0.000153
1) 0.000108 77% 0.000129 0.000129 0.000134 0.000132 0.000127 81% 0.000151 0.000147 0.000127 80% 0.000152 0.000149
revset #25: (20000::) - (20000)
plain min max first last reverse rev..rst rev..ast sort sor..rst sor..ast
0) 0.050560 0.045513 0.022593 0.043588 0.021909 0.045517 0.021822 0.044660 0.049740 0.044227 0.021819
1) 0.018614 36% 0.000171 0% 0.019659 87% 0.000168 0% 0.015543 70% 0.021069 46% 0.015623 71% 0.000180 0% 0.018658 37% 0.000186 0% 0.015750 72%
author | Durham Goode <durham@fb.com> |
---|---|
date | Wed, 24 Feb 2016 10:41:15 -0800 |
parents | eed7d8c07c20 |
children | 41dcd7545266 |
files | mercurial/revset.py tests/test-revset.t |
diffstat | 2 files changed, 9 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/revset.py Tue Feb 23 21:38:36 2016 +0000 +++ b/mercurial/revset.py Wed Feb 24 10:41:15 2016 -0800 @@ -436,6 +436,9 @@ def andset(repo, subset, x, y): return getset(repo, getset(repo, subset, x), y) +def differenceset(repo, subset, x, y): + return getset(repo, subset, x) - getset(repo, subset, y) + def orset(repo, subset, *xs): assert xs if len(xs) == 1: @@ -2147,6 +2150,7 @@ "and": andset, "or": orset, "not": notset, + "difference": differenceset, "list": listset, "keyvalue": keyvaluepair, "func": func, @@ -2207,6 +2211,9 @@ if isonly(tb, ta): return w, ('func', ('symbol', 'only'), ('list', tb[2], ta[1][2])) + if tb is not None and tb[0] == 'not': + return wa, ('difference', ta, tb[1]) + if wa > wb: return w, (op, tb, ta) return w, (op, ta, tb)
--- a/tests/test-revset.t Tue Feb 23 21:38:36 2016 +0000 +++ b/tests/test-revset.t Wed Feb 24 10:41:15 2016 -0800 @@ -693,12 +693,11 @@ * optimized: (func ('symbol', 'only') - (and + (difference (range ('symbol', '8') ('symbol', '9')) - (not - ('symbol', '8')))) + ('symbol', '8'))) * set: <baseset+ [8, 9]> 8