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):