Mercurial > hg
comparison mercurial/dagop.py @ 42446:055c3e2c44f0
revlog: speed up isancestor
Currently, it is implemented on top of commonancestorsheads.
Implement it on top of reachableroots instead, as reachableroots could
stop walking the graph much sooner than commonancestorsheads.
Measuring repo.changelog.isancestorrev on two revisions in a private repository:
before: ! wall 0.005175 comb 0.010000 user 0.010000 sys 0.000000 (best of 550)
after : ! wall 0.000072 comb 0.000000 user 0.000000 sys 0.000000 (best of 36199)
When hg does this kind of operations 1500 times in pull ->
bookmarks.comparebookmarks -> bookmarks.validdest, that's 11s that
drop from the --profile output.
Differential Revision: https://phab.mercurial-scm.org/D6506
author | Valentin Gatien-Baron <vgatien-baron@janestreet.com> |
---|---|
date | Mon, 10 Jun 2019 13:23:14 -0400 |
parents | 3e42fc243741 |
children | 2372284d9457 |
comparison
equal
deleted
inserted
replaced
42445:3e42fc243741 | 42446:055c3e2c44f0 |
---|---|
257 if prev != nullrev and prev in seen: | 257 if prev != nullrev and prev in seen: |
258 seen.add(rev) | 258 seen.add(rev) |
259 yield rev | 259 yield rev |
260 break | 260 break |
261 | 261 |
262 def _reachablerootspure(repo, minroot, roots, heads, includepath): | 262 def _reachablerootspure(pfunc, minroot, roots, heads, includepath): |
263 """See reachableroots""" | 263 """See revlog.reachableroots""" |
264 if not roots: | 264 if not roots: |
265 return [] | 265 return [] |
266 parentrevs = repo.changelog.parentrevs | |
267 roots = set(roots) | 266 roots = set(roots) |
268 visit = list(heads) | 267 visit = list(heads) |
269 reachable = set() | 268 reachable = set() |
270 seen = {} | 269 seen = {} |
271 # prefetch all the things! (because python is slow) | 270 # prefetch all the things! (because python is slow) |
278 rev = nextvisit() | 277 rev = nextvisit() |
279 if rev in roots: | 278 if rev in roots: |
280 reached(rev) | 279 reached(rev) |
281 if not includepath: | 280 if not includepath: |
282 continue | 281 continue |
283 parents = parentrevs(rev) | 282 parents = pfunc(rev) |
284 seen[rev] = parents | 283 seen[rev] = parents |
285 for parent in parents: | 284 for parent in parents: |
286 if parent >= minroot and parent not in seen: | 285 if parent >= minroot and parent not in seen: |
287 dovisit(parent) | 286 dovisit(parent) |
288 if not reachable: | 287 if not reachable: |
294 if parent in reachable: | 293 if parent in reachable: |
295 reached(rev) | 294 reached(rev) |
296 return reachable | 295 return reachable |
297 | 296 |
298 def reachableroots(repo, roots, heads, includepath=False): | 297 def reachableroots(repo, roots, heads, includepath=False): |
299 """return (heads(::<roots> and <roots>::<heads>)) | 298 """See revlog.reachableroots""" |
300 | |
301 If includepath is True, return (<roots>::<heads>).""" | |
302 if not roots: | 299 if not roots: |
303 return baseset() | 300 return baseset() |
304 minroot = roots.min() | 301 minroot = roots.min() |
305 roots = list(roots) | 302 roots = list(roots) |
306 heads = list(heads) | 303 heads = list(heads) |
307 try: | 304 revs = repo.changelog.reachableroots(minroot, heads, roots, includepath) |
308 revs = repo.changelog.reachableroots(minroot, heads, roots, includepath) | |
309 except AttributeError: | |
310 revs = _reachablerootspure(repo, minroot, roots, heads, includepath) | |
311 revs = baseset(revs) | 305 revs = baseset(revs) |
312 revs.sort() | 306 revs.sort() |
313 return revs | 307 return revs |
314 | 308 |
315 def _changesrange(fctx1, fctx2, linerange2, diffopts): | 309 def _changesrange(fctx1, fctx2, linerange2, diffopts): |