Mercurial > public > mercurial-scm > hg
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 |