Mercurial > public > mercurial-scm > hg
comparison mercurial/cmdutil.py @ 18171:9d350f2d9458
cmdutil: stop pretending we can calculate revs for graphlog lazily
cmdutil.getgraphlogrevs does a ton of work trying to build a graphlog lazily,
and then cmdutil.graphlog comes along and destroys all of that.
graphmod.dagwalker requires that it be given the full list of revs upfront so
that it can perform filtering and tests against known revs.
For a repository with over 400,000 changesets, this speeds up graphlog by
around 0.02 seconds (~20% with a small limit).
author | Siddharth Agarwal <sid0@fb.com> |
---|---|
date | Fri, 28 Dec 2012 16:25:00 -0800 |
parents | 0dcc77b271b9 |
children | e6c5e0092469 |
comparison
equal
deleted
inserted
replaced
18170:0dcc77b271b9 | 18171:9d350f2d9458 |
---|---|
1397 and file patterns or None, and used to filter 'revs'. If --stat or | 1397 and file patterns or None, and used to filter 'revs'. If --stat or |
1398 --patch are not passed filematcher is None. Otherwise it is a | 1398 --patch are not passed filematcher is None. Otherwise it is a |
1399 callable taking a revision number and returning a match objects | 1399 callable taking a revision number and returning a match objects |
1400 filtering the files to be detailed when displaying the revision. | 1400 filtering the files to be detailed when displaying the revision. |
1401 """ | 1401 """ |
1402 def increasingrevs(repo, revs, matcher): | |
1403 # The sorted input rev sequence is chopped in sub-sequences | |
1404 # which are sorted in ascending order and passed to the | |
1405 # matcher. The filtered revs are sorted again as they were in | |
1406 # the original sub-sequence. This achieve several things: | |
1407 # | |
1408 # - getlogrevs() now returns a generator which behaviour is | |
1409 # adapted to log need. First results come fast, last ones | |
1410 # are batched for performances. | |
1411 # | |
1412 # - revset matchers often operate faster on revision in | |
1413 # changelog order, because most filters deal with the | |
1414 # changelog. | |
1415 # | |
1416 # - revset matchers can reorder revisions. "A or B" typically | |
1417 # returns returns the revision matching A then the revision | |
1418 # matching B. We want to hide this internal implementation | |
1419 # detail from the caller, and sorting the filtered revision | |
1420 # again achieves this. | |
1421 for i, window in increasingwindows(0, len(revs), windowsize=1): | |
1422 orevs = revs[i:i + window] | |
1423 nrevs = set(matcher(repo, sorted(orevs))) | |
1424 for rev in orevs: | |
1425 if rev in nrevs: | |
1426 yield rev | |
1427 | |
1428 if not len(repo): | 1402 if not len(repo): |
1429 return iter([]), None, None | 1403 return [], None, None |
1430 # Default --rev value depends on --follow but --follow behaviour | 1404 # Default --rev value depends on --follow but --follow behaviour |
1431 # depends on revisions resolved from --rev... | 1405 # depends on revisions resolved from --rev... |
1432 follow = opts.get('follow') or opts.get('follow_first') | 1406 follow = opts.get('follow') or opts.get('follow_first') |
1433 possiblyunsorted = False # whether revs might need sorting | 1407 possiblyunsorted = False # whether revs might need sorting |
1434 if opts.get('rev'): | 1408 if opts.get('rev'): |
1441 revs = repo.revs('reverse(:.)') | 1415 revs = repo.revs('reverse(:.)') |
1442 else: | 1416 else: |
1443 revs = list(repo.changelog) | 1417 revs = list(repo.changelog) |
1444 revs.reverse() | 1418 revs.reverse() |
1445 if not revs: | 1419 if not revs: |
1446 return iter([]), None, None | 1420 return [], None, None |
1447 expr, filematcher = _makegraphlogrevset(repo, pats, opts, revs) | 1421 expr, filematcher = _makegraphlogrevset(repo, pats, opts, revs) |
1448 if possiblyunsorted: | 1422 if possiblyunsorted: |
1449 revs.sort(reverse=True) | 1423 revs.sort(reverse=True) |
1450 if expr: | 1424 if expr: |
1425 # Revset matchers often operate faster on revisions in changelog | |
1426 # order, because most filters deal with the changelog. | |
1427 revs.reverse() | |
1451 matcher = revset.match(repo.ui, expr) | 1428 matcher = revset.match(repo.ui, expr) |
1452 revs = increasingrevs(repo, revs, matcher) | 1429 # Revset matches can reorder revisions. "A or B" typically returns |
1430 # returns the revision matching A then the revision matching B. Sort | |
1431 # again to fix that. | |
1432 revs = matcher(repo, revs) | |
1433 revs.sort(reverse=True) | |
1453 if not opts.get('hidden'): | 1434 if not opts.get('hidden'): |
1454 # --hidden is still experimental and not worth a dedicated revset | 1435 # --hidden is still experimental and not worth a dedicated revset |
1455 # yet. Fortunately, filtering revision number is fast. | 1436 # yet. Fortunately, filtering revision number is fast. |
1456 hiddenrevs = repo.hiddenrevs | 1437 hiddenrevs = repo.hiddenrevs |
1457 revs = (r for r in revs if r not in hiddenrevs) | 1438 revs = [r for r in revs if r not in hiddenrevs] |
1458 else: | |
1459 revs = iter(revs) | |
1460 return revs, expr, filematcher | 1439 return revs, expr, filematcher |
1461 | 1440 |
1462 def displaygraph(ui, dag, displayer, showparents, edgefn, getrenamed=None, | 1441 def displaygraph(ui, dag, displayer, showparents, edgefn, getrenamed=None, |
1463 filematcher=None): | 1442 filematcher=None): |
1464 seen, state = [], graphmod.asciistate() | 1443 seen, state = [], graphmod.asciistate() |
1489 displayer.close() | 1468 displayer.close() |
1490 | 1469 |
1491 def graphlog(ui, repo, *pats, **opts): | 1470 def graphlog(ui, repo, *pats, **opts): |
1492 # Parameters are identical to log command ones | 1471 # Parameters are identical to log command ones |
1493 revs, expr, filematcher = getgraphlogrevs(repo, pats, opts) | 1472 revs, expr, filematcher = getgraphlogrevs(repo, pats, opts) |
1494 revs = sorted(revs, reverse=1) | |
1495 limit = loglimit(opts) | 1473 limit = loglimit(opts) |
1496 if limit is not None: | 1474 if limit is not None: |
1497 revs = revs[:limit] | 1475 revs = revs[:limit] |
1498 revdag = graphmod.dagwalker(repo, revs) | 1476 revdag = graphmod.dagwalker(repo, revs) |
1499 | 1477 |