comparison mercurial/revset.py @ 23787:678f53865c68

revset: use localrepo revbranchcache for branch name filtering Branch name filtering in revsets was expensive. For every rev it created a changectx and called .branch() which retrieved the branch name from the changelog. Instead, use the revbranchcache. The revbranchcache is used read-only. The revset implementation with generators and callbacks makes it hard to figure out when we are done using/updating the cache and could write it back. It would also be 'tricky' to lock the repo for writing from within a revset execution. Finally, the branchmap update will usually make sure that the cache is updated before any revset can be run. The revbranchcache is used without any locking but is short-lived and used in a tight loop where we can assume that the changelog doesn't change ... or where it not is relevant to us if it does. perfrevset 'branch(mobile)' on mozilla-central. Before: ! wall 10.989637 comb 10.970000 user 10.940000 sys 0.030000 (best of 3) After, no cache: ! wall 7.368656 comb 7.370000 user 7.360000 sys 0.010000 (best of 3) After, with cache: ! wall 0.528098 comb 0.530000 user 0.530000 sys 0.000000 (best of 18) The performance improvement even without cache come from being based on branchinfo on the changelog instead of using ctx.branch(). Some tests are added to verify that the revbranchcache works and keep an eye on when the cache files actually are updated.
author Mads Kiilerich <madski@unity3d.com>
date Thu, 08 Jan 2015 00:01:03 +0100
parents 537a2669a113
children 60178888be05
comparison
equal deleted inserted replaced
23786:7d63398fbfd1 23787:678f53865c68
455 455
456 If `string` starts with `re:`, the remainder of the name is treated as 456 If `string` starts with `re:`, the remainder of the name is treated as
457 a regular expression. To match a branch that actually starts with `re:`, 457 a regular expression. To match a branch that actually starts with `re:`,
458 use the prefix `literal:`. 458 use the prefix `literal:`.
459 """ 459 """
460 import branchmap
461 urepo = repo.unfiltered()
462 ucl = urepo.changelog
463 getbi = branchmap.revbranchcache(urepo).branchinfo
464
460 try: 465 try:
461 b = getstring(x, '') 466 b = getstring(x, '')
462 except error.ParseError: 467 except error.ParseError:
463 # not a string, but another revspec, e.g. tip() 468 # not a string, but another revspec, e.g. tip()
464 pass 469 pass
466 kind, pattern, matcher = _stringmatcher(b) 471 kind, pattern, matcher = _stringmatcher(b)
467 if kind == 'literal': 472 if kind == 'literal':
468 # note: falls through to the revspec case if no branch with 473 # note: falls through to the revspec case if no branch with
469 # this name exists 474 # this name exists
470 if pattern in repo.branchmap(): 475 if pattern in repo.branchmap():
471 return subset.filter(lambda r: matcher(repo[r].branch())) 476 return subset.filter(lambda r: matcher(getbi(ucl, r)[0]))
472 else: 477 else:
473 return subset.filter(lambda r: matcher(repo[r].branch())) 478 return subset.filter(lambda r: matcher(getbi(ucl, r)[0]))
474 479
475 s = getset(repo, spanset(repo), x) 480 s = getset(repo, spanset(repo), x)
476 b = set() 481 b = set()
477 for r in s: 482 for r in s:
478 b.add(repo[r].branch()) 483 b.add(getbi(ucl, r)[0])
479 c = s.__contains__ 484 c = s.__contains__
480 return subset.filter(lambda r: c(r) or repo[r].branch() in b) 485 return subset.filter(lambda r: c(r) or getbi(ucl, r)[0] in b)
481 486
482 def bumped(repo, subset, x): 487 def bumped(repo, subset, x):
483 """``bumped()`` 488 """``bumped()``
484 Mutable changesets marked as successors of public changesets. 489 Mutable changesets marked as successors of public changesets.
485 490