Patchwork [3,of,6,V5] revset: remove grandparent by using reachableroots

login
register
mail settings
Submitter Pierre-Yves David
Date Aug. 7, 2015, 9:06 p.m.
Message ID <9965ba0c40447c09e998.1438981612@marginatus.alto.octopoid.net>
Download mbox | patch
Permalink /patch/10154/
State Accepted
Headers show

Comments

Pierre-Yves David - Aug. 7, 2015, 9:06 p.m.
# HG changeset patch
# User Laurent Charignon <lcharignon@fb.com>
# Date 1434770932 25200
#      Fri Jun 19 20:28:52 2015 -0700
# Node ID 9965ba0c40447c09e998d84024c23444b2ee5d95
# Parent  5f55544d6c5187bbf31ab4cc851f094867421430
revset: remove grandparent by using reachableroots

This patch is part of a series of patches to speed up the computation of
revset.reachableroots by introducing a C implementation. The main motivation
is to speed up smartlog on big repositories. At the end of the series, on our
big repositories the computation of reachableroots is 10-50x faster and
smartlog on is 2x-5x faster.

Before this patch, we had a custom computation for grandparent that was very
close to the idea of reacheablerooots. This patch expresses grandparent with
reachableroots to reduce the amount of code.

Patch

diff --git a/mercurial/graphmod.py b/mercurial/graphmod.py
--- a/mercurial/graphmod.py
+++ b/mercurial/graphmod.py
@@ -17,10 +17,11 @@  context of the graph returned. Type is a
 Data depends on type.
 """
 
 from mercurial.node import nullrev
 import util
+import revset
 
 import heapq
 
 CHANGESET = 'C'
 
@@ -231,12 +232,10 @@  def dagwalker(repo, revs):
     returned.
     """
     if not revs:
         return
 
-    cl = repo.changelog
-    lowestrev = revs.min()
     gpcache = {}
 
     if repo.ui.configbool('experimental', 'graph-group-branches', False):
         firstbranch = ()
         firstbranchrevset = repo.ui.config(
@@ -254,11 +253,11 @@  def dagwalker(repo, revs):
                  p.rev() != nullrev and p.rev() not in parents]
 
         for mpar in mpars:
             gp = gpcache.get(mpar)
             if gp is None:
-                gp = gpcache[mpar] = grandparent(cl, lowestrev, revs, mpar)
+                gp = gpcache[mpar] = revset.reachableroots(repo, revs, [mpar])
             if not gp:
                 parents.append(mpar)
             else:
                 parents.extend(g for g in gp if g not in parents)
 
@@ -352,28 +351,10 @@  def colored(dag, repo):
 
         # Yield and move on
         yield (cur, type, data, (col, color), edges)
         seen = next
 
-def grandparent(cl, lowestrev, roots, head):
-    """Return all ancestors of head in roots which revision is
-    greater or equal to lowestrev.
-    """
-    pending = set([head])
-    seen = set()
-    kept = set()
-    llowestrev = max(nullrev, lowestrev)
-    while pending:
-        r = pending.pop()
-        if r >= llowestrev and r not in seen:
-            if r in roots:
-                kept.add(r)
-            else:
-                pending.update([p for p in cl.parentrevs(r)])
-            seen.add(r)
-    return sorted(kept)
-
 def asciiedges(type, char, lines, seen, rev, parents):
     """adds edge info to changelog DAG walk suitable for ascii()"""
     if rev not in seen:
         seen.append(rev)
     nodeidx = seen.index(rev)