[PATCH 7 of 9 "] discovery: move children computation in its own method

Pierre-Yves David pierre-yves.david at ens-lyon.org
Tue Mar 5 12:39:18 EST 2019


# HG changeset patch
# User Pierre-Yves David <pierre-yves.david at octobus.net>
# Date 1551312945 -3600
#      Thu Feb 28 01:15:45 2019 +0100
# Node ID fe57cbd053432d10bccd3955072a4c6c581e3355
# Parent  1d2a2e4a255fcc8e5713232f5f80858a7b3793e1
# EXP-Topic discovery-speedup
# Available At https://bitbucket.org/octobus/mercurial-devel/
#              hg pull https://bitbucket.org/octobus/mercurial-devel/ -r fe57cbd05343
discovery: move children computation in its own method

This clarifies the main logic and starts to pave the way to some caching.

diff --git a/mercurial/setdiscovery.py b/mercurial/setdiscovery.py
--- a/mercurial/setdiscovery.py
+++ b/mercurial/setdiscovery.py
@@ -171,6 +171,32 @@ class partialdiscovery(object):
             return getrev(r)[5:6]
         return getparents
 
+    def _childrengetter(self, revs):
+
+        # _updatesample() essentially does interaction over revisions to look
+        # up their children. This lookup is expensive and doing it in a loop is
+        # quadratic. We precompute the children for all relevant revisions and
+        # make the lookup in _updatesample() a simple dict lookup.
+        #
+        # Because this function can be called multiple times during discovery,
+        # we may still perform redundant work and there is room to optimize
+        # this by keeping a persistent cache of children across invocations.
+        children = {}
+
+        parentrevs = self._parentsgetter()
+
+        for rev in sorted(revs):
+            # Always ensure revision has an entry so we don't need to worry
+            # about missing keys.
+            children[rev] = []
+            for prev in parentrevs(rev):
+                if prev == nullrev:
+                    continue
+                c = children.get(prev)
+                if c is not None:
+                    c.append(rev)
+        return children.__getitem__
+
     def takequicksample(self, headrevs, size):
         """takes a quick sample of size <size>
 
@@ -206,28 +232,9 @@ class partialdiscovery(object):
         # update from roots
         revsroots = set(repo.revs('roots(%ld)', revs))
 
-        # _updatesample() essentially does interaction over revisions to look
-        # up their children. This lookup is expensive and doing it in a loop is
-        # quadratic. We precompute the children for all relevant revisions and
-        # make the lookup in _updatesample() a simple dict lookup.
-        #
-        # Because this function can be called multiple times during discovery,
-        # we may still perform redundant work and there is room to optimize
-        # this by keeping a persistent cache of children across invocations.
-        children = {}
+        childrenrevs = self._childrengetter(revs)
 
-        for rev in sorted(revs):
-            # Always ensure revision has an entry so we don't need to worry
-            # about missing keys.
-            children[rev] = []
-            for prev in parentrevs(rev):
-                if prev == nullrev:
-                    continue
-                c = children.get(prev)
-                if c is not None:
-                    c.append(rev)
-
-        _updatesample(revs, revsroots, sample, children.__getitem__)
+        _updatesample(revs, revsroots, sample, childrenrevs)
         assert sample
         sample = _limitsample(sample, size)
         if len(sample) < size:


More information about the Mercurial-devel mailing list