Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/graphmod.py @ 14087:f3d585c9b042
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
author | Idan Kamara <idankk86@gmail.com> |
---|---|
date | Sat, 30 Apr 2011 15:10:58 +0300 |
parents | e4bfb9c337f3 |
children | e83ced8b6464 |
comparison
equal
deleted
inserted
replaced
14086:2d7cb340a53f | 14087:f3d585c9b042 |
---|---|
28 from bigger to lower). It returns a tuple for each node. The node and parent | 28 from bigger to lower). It returns a tuple for each node. The node and parent |
29 ids are arbitrary integers which identify a node in the context of the graph | 29 ids are arbitrary integers which identify a node in the context of the graph |
30 returned. | 30 returned. |
31 """ | 31 """ |
32 if not revs: | 32 if not revs: |
33 return [] | 33 return |
34 | |
35 ns = [repo[r].node() for r in revs] | |
36 revdag = list(nodes(repo, ns)) | |
37 | 34 |
38 cl = repo.changelog | 35 cl = repo.changelog |
39 lowestrev = min(revs) | 36 lowestrev = min(revs) |
40 gpcache = {} | 37 gpcache = {} |
41 leafs = {} | |
42 | 38 |
43 for i, (id, c, ctx, parents) in enumerate(revdag): | 39 for rev in revs: |
40 ctx = repo[rev] | |
41 parents = sorted(set([p.rev() for p in ctx.parents() if p.rev() in revs])) | |
44 mpars = [p.rev() for p in ctx.parents() if | 42 mpars = [p.rev() for p in ctx.parents() if |
45 p.rev() != nullrev and p.rev() not in parents] | 43 p.rev() != nullrev and p.rev() not in parents] |
46 grandparents = [] | |
47 | 44 |
48 for mpar in mpars: | 45 for mpar in mpars: |
49 gp = gpcache.get(mpar) or grandparent(cl, lowestrev, revs, mpar) | 46 gp = gpcache.get(mpar) or grandparent(cl, lowestrev, revs, mpar) |
50 gpcache[mpar] = gp | 47 gpcache[mpar] = gp |
51 if gp is None: | 48 if gp is None: |
52 leafs.setdefault(mpar, []).append((i, ctx)) | 49 parents.append(mpar) |
53 else: | 50 elif gp not in parents: |
54 grandparents.append(gp) | 51 parents.append(gp) |
55 | 52 |
56 if grandparents: | 53 yield (ctx.rev(), CHANGESET, ctx, parents) |
57 for gp in grandparents: | |
58 if gp not in revdag[i][3]: | |
59 revdag[i][3].append(gp) | |
60 | |
61 for parent, leafs in leafs.iteritems(): | |
62 for i, ctx in leafs: | |
63 revdag[i][3].append(parent) | |
64 | |
65 return revdag | |
66 | 54 |
67 def nodes(repo, nodes): | 55 def nodes(repo, nodes): |
68 """cset DAG generator yielding (id, CHANGESET, ctx, [parentids]) tuples | 56 """cset DAG generator yielding (id, CHANGESET, ctx, [parentids]) tuples |
69 | 57 |
70 This generator function walks the given nodes. It only returns parents | 58 This generator function walks the given nodes. It only returns parents |