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