# HG changeset patch # User Idan Kamara # Date 1304165458 -10800 # Node ID f3d585c9b042cfa208733e3e128429c6a7b7dd52 # Parent 2d7cb340a53f01f181e4b3b9a9e5310772996a3f graphmod: restore generator nature of dagwalker 9966c95b8c4f introduced the ability to walk the DAG given arbitrary revisions, but changed the behaviour of it to return a list of all nodes (and create a changectx for each one) rather than doing it lazily. This has a pretty significant impact on performance for large repositories (tested on CPython repo, with output disabled): $ time hg glog real 0m2.642s user 0m2.560s sys 0m0.080s Before 9966c95b8c4f: $ time hg glog real 0m0.143s user 0m0.112s sys 0m0.032s And after this fix: $ time hg glog real 0m0.213s user 0m0.184s sys 0m0.028s diff -r 2d7cb340a53f -r f3d585c9b042 mercurial/graphmod.py --- a/mercurial/graphmod.py Sat Apr 30 19:42:00 2011 +0200 +++ b/mercurial/graphmod.py Sat Apr 30 15:10:58 2011 +0300 @@ -30,39 +30,27 @@ returned. """ if not revs: - return [] - - ns = [repo[r].node() for r in revs] - revdag = list(nodes(repo, ns)) + return cl = repo.changelog lowestrev = min(revs) gpcache = {} - leafs = {} - for i, (id, c, ctx, parents) in enumerate(revdag): + for rev in revs: + ctx = repo[rev] + parents = sorted(set([p.rev() for p in ctx.parents() if p.rev() in revs])) mpars = [p.rev() for p in ctx.parents() if p.rev() != nullrev and p.rev() not in parents] - grandparents = [] for mpar in mpars: gp = gpcache.get(mpar) or grandparent(cl, lowestrev, revs, mpar) gpcache[mpar] = gp if gp is None: - leafs.setdefault(mpar, []).append((i, ctx)) - else: - grandparents.append(gp) + parents.append(mpar) + elif gp not in parents: + parents.append(gp) - if grandparents: - for gp in grandparents: - if gp not in revdag[i][3]: - revdag[i][3].append(gp) - - for parent, leafs in leafs.iteritems(): - for i, ctx in leafs: - revdag[i][3].append(parent) - - return revdag + yield (ctx.rev(), CHANGESET, ctx, parents) def nodes(repo, nodes): """cset DAG generator yielding (id, CHANGESET, ctx, [parentids]) tuples