scmutil: speed up revrange
authorBryan O'Sullivan <bryano@fb.com>
Mon, 09 Apr 2012 22:16:26 -0700
changeset 16390 4df76d5506a9
parent 16389 79fecd735d26
child 16391 9cf7c9d529d0
scmutil: speed up revrange This improves the performance of "hg log -l1" from 0.21 seconds to 0.07 on a Linux kernel tree. Ideally we could use xrange instead of range on the most common path, and thus avoid a ton of allocation, but xrange doesn't support slice-based indexing.
mercurial/scmutil.py
--- a/mercurial/scmutil.py	Tue Apr 10 12:49:12 2012 -0500
+++ b/mercurial/scmutil.py	Mon Apr 09 22:16:26 2012 -0700
@@ -534,6 +534,8 @@
 
     seen, l = set(), []
     for spec in revs:
+        if l and not seen:
+            seen = set(l)
         # attempt to parse old-style ranges first to deal with
         # things like old-tag which contain query metacharacters
         try:
@@ -547,11 +549,18 @@
                 start = revfix(repo, start, 0)
                 end = revfix(repo, end, len(repo) - 1)
                 step = start > end and -1 or 1
-                for rev in xrange(start, end + step, step):
-                    if rev in seen:
-                        continue
-                    seen.add(rev)
-                    l.append(rev)
+                if not seen and not l:
+                    # by far the most common case: revs = ["-1:0"]
+                    l = range(start, end + step, step)
+                    # defer syncing seen until next iteration
+                    continue
+                newrevs = set(xrange(start, end + step, step))
+                if seen:
+                    newrevs.difference_update(seen)
+                    seen.union(newrevs)
+                else:
+                    seen = newrevs
+                l.extend(sorted(newrevs, reverse=start > end))
                 continue
             elif spec and spec in repo: # single unquoted rev
                 rev = revfix(repo, spec, None)