changeset 20553:86cefb15e7b5

cmdutil: implemented new lazy increasingwindows Now log can work in a lazy way and get results as soon as they are processed. Performance Benchmarking: $ time hg log -l1 -qr "branch(default)" 0:9117c6561b0b real 0m2.303s user 0m2.252s sys 0m0.048s $ time ./hg log -l1 -qr "branch(default)" 0:9117c6561b0b real 0m0.238s user 0m0.199s sys 0m0.037s
author Lucas Moscovicz <lmoscovicz@fb.com>
date Thu, 13 Feb 2014 14:27:12 -0800
parents 0e99a66eb7bc
children 24e0661e6c2e
files mercurial/cmdutil.py
diffstat 1 files changed, 23 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/cmdutil.py	Thu Feb 20 10:15:38 2014 -0800
+++ b/mercurial/cmdutil.py	Thu Feb 13 14:27:12 2014 -0800
@@ -1133,19 +1133,11 @@
 
     raise util.Abort(_("revision matching date not found"))
 
-def increasingwindows(start, end, windowsize=8, sizelimit=512):
-    if start < end:
-        while start < end:
-            yield start, min(windowsize, end - start)
-            start += windowsize
-            if windowsize < sizelimit:
-                windowsize *= 2
-    else:
-        while start > end:
-            yield start, min(windowsize, start - end - 1)
-            start -= windowsize
-            if windowsize < sizelimit:
-                windowsize *= 2
+def increasingwindows(windowsize=8, sizelimit=512):
+    while True:
+        yield windowsize
+        if windowsize < sizelimit:
+            windowsize *= 2
 
 class FileWalkError(Exception):
     pass
@@ -1278,7 +1270,6 @@
     slowpath = match.anypats() or (match.files() and opts.get('removed'))
     fncache = {}
     change = repo.changectx
-    revs = revset.baseset(revs)
 
     # First step is to fill wanted, the set of revisions that we want to yield.
     # When it does not induce extra cost, we also fill fncache for revisions in
@@ -1287,7 +1278,7 @@
 
     if not slowpath and not match.files():
         # No files, no patterns.  Display all revs.
-        wanted = set(revs)
+        wanted = revs
 
     if not slowpath and match.files():
         # We only have to read through the filelog to find wanted revisions
@@ -1389,14 +1380,7 @@
         stop = min(revs[0], revs[-1])
         for x in xrange(rev, stop - 1, -1):
             if ff.match(x):
-                wanted.discard(x)
-
-    # Choose a small initial window if we will probably only visit a
-    # few commits.
-    limit = loglimit(opts)
-    windowsize = 8
-    if limit:
-        windowsize = min(limit, windowsize)
+                wanted = wanted - [x]
 
     # Now that wanted is correctly initialized, we can iterate over the
     # revision range, yielding only revisions in wanted.
@@ -1409,8 +1393,18 @@
             def want(rev):
                 return rev in wanted
 
-        for i, window in increasingwindows(0, len(revs), windowsize):
-            nrevs = [rev for rev in revs[i:i + window] if want(rev)]
+        it = iter(revs)
+        stopiteration = False
+        for windowsize in increasingwindows():
+            nrevs = []
+            for i in xrange(windowsize):
+                try:
+                    rev = it.next()
+                    if want(rev):
+                        nrevs.append(rev)
+                except (StopIteration):
+                    stopiteration = True
+                    break
             for rev in sorted(nrevs):
                 fns = fncache.get(rev)
                 ctx = change(rev)
@@ -1423,6 +1417,10 @@
                 prepare(ctx, fns)
             for rev in nrevs:
                 yield change(rev)
+
+            if stopiteration:
+                break
+
     return iterate()
 
 def _makegraphfilematcher(repo, pats, followfirst):