changeset 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 2d7cb340a53f
children e83ced8b6464
files mercurial/graphmod.py
diffstat 1 files changed, 8 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- 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