comparison mercurial/revset.py @ 26006:1ffd97cbf9a2

reachableroots: default to the C implementation This patch is part of a series of patches to speed up the computation of revset.reachableroots by introducing a C implementation. The main motivation is to speed up smartlog on big repositories. At the end of the series, on our big repositories the computation of reachableroots is 10-50x faster and smartlog on is 2x-5x faster. Before this patch, reachableroots was computed in pure Python by default. This patch makes the C implementation the default and provides a speedup for reachableroots.
author Laurent Charignon <lcharignon@fb.com>
date Thu, 06 Aug 2015 22:11:20 -0700
parents fd92bfbbe02d
children b68c9d232db6
comparison
equal deleted inserted replaced
26005:6f4a280298c1 26006:1ffd97cbf9a2
85 yield i 85 yield i
86 break 86 break
87 87
88 return generatorset(iterate(), iterasc=True) 88 return generatorset(iterate(), iterasc=True)
89 89
90 def reachableroots(repo, roots, heads, includepath=False): 90 def reachablerootspure(repo, minroot, roots, heads, includepath):
91 """return (heads(::<roots> and ::<heads>)) 91 """return (heads(::<roots> and ::<heads>))
92 92
93 If includepath is True, return (<roots>::<heads>).""" 93 If includepath is True, return (<roots>::<heads>)."""
94 if not roots: 94 if not roots:
95 return baseset() 95 return baseset()
96 parentrevs = repo.changelog.parentrevs 96 parentrevs = repo.changelog.parentrevs
97 visit = list(heads) 97 visit = list(heads)
98 reachable = set() 98 reachable = set()
99 seen = {} 99 seen = {}
100 # XXX this should be 'parentset.min()' assuming 'parentset' is a smartset
101 # (and if it is not, it should.)
102 minroot = min(roots)
103 roots = set(roots)
104 # prefetch all the things! (because python is slow) 100 # prefetch all the things! (because python is slow)
105 reached = reachable.add 101 reached = reachable.add
106 dovisit = visit.append 102 dovisit = visit.append
107 nextvisit = visit.pop 103 nextvisit = visit.pop
108 # open-code the post-order traversal due to the tiny size of 104 # open-code the post-order traversal due to the tiny size of
125 for rev in sorted(seen): 121 for rev in sorted(seen):
126 for parent in seen[rev]: 122 for parent in seen[rev]:
127 if parent in reachable: 123 if parent in reachable:
128 reached(rev) 124 reached(rev)
129 return baseset(sorted(reachable)) 125 return baseset(sorted(reachable))
126
127 def reachableroots(repo, roots, heads, includepath=False):
128 """return (heads(::<roots> and ::<heads>))
129
130 If includepath is True, return (<roots>::<heads>)."""
131 if not roots:
132 return baseset()
133 # XXX this should be 'parentset.min()' assuming 'parentset' is a smartset
134 # (and if it is not, it should.)
135 minroot = min(roots)
136 roots = set(roots)
137 heads = list(heads)
138 try:
139 return repo.changelog.reachableroots(minroot, heads, roots, includepath)
140 except AttributeError:
141 return reachablerootspure(repo, minroot, roots, heads, includepath)
130 142
131 elements = { 143 elements = {
132 # token-type: binding-strength, primary, prefix, infix, suffix 144 # token-type: binding-strength, primary, prefix, infix, suffix
133 "(": (21, None, ("group", 1, ")"), ("func", 1, ")"), None), 145 "(": (21, None, ("group", 1, ")"), ("func", 1, ")"), None),
134 "##": (20, None, None, ("_concat", 20), None), 146 "##": (20, None, None, ("_concat", 20), None),