[PATCH 5 of 7] revset: introduce a filterrevs function

Bryan O'Sullivan bos at serpentine.com
Mon Jun 4 17:25:11 CDT 2012


# HG changeset patch
# User Bryan O'Sullivan <bryano at fb.com>
# Date 1338848634 25200
# Node ID 1fda5b47f842b8b57ee866684aaabcc1052a06e1
# Parent  115c3e5c708813a9800dfe4938a7c9202a4d00ba
revset: introduce a filterrevs function

For large revsets, our pattern of always creating new lists is
expensive.  This function tries to avoid unnecessary list duplication.

As an example, here's performance on a kernel repo with "hg
perfrevrange 2222::233333".

Before: 0.572 sec
After:  0.461 sec (20% better)

diff --git a/mercurial/revset.py b/mercurial/revset.py
--- a/mercurial/revset.py
+++ b/mercurial/revset.py
@@ -84,6 +84,21 @@ def revsubset(subset):
         return set(subset)
     return _revinterval(subset)
 
+def filterrevs(revs, subset, contig=False):
+    if not revs:
+        return revs
+    subset = revsubset(subset)
+    try:
+        if contig or isinstance(revs, (_revinterval, xrange)):
+            lo, hi = sorted((revs[0], revs[-1]))
+        else:
+            lo, hi = min(revs), max(revs)
+        if subset._start <= lo and subset._stop > hi:
+            return revs
+    except (AttributeError, TypeError, KeyError):
+        pass
+    return filter(subset.__contains__, revs)
+
 def _revancestors(repo, revs, followfirst):
     """Like revlog.ancestors(), but supports followfirst."""
     cut = followfirst and 1 or None
@@ -296,8 +311,7 @@ def dagrange(repo, subset, x, y):
     if subset:
         r = revsubset(repo)
         xs = _revsbetween(repo, getset(repo, r, x), getset(repo, r, y))
-        s = revsubset(subset)
-        return [r for r in xs if r in s]
+        return filterrevs(xs, subset, contig=True)
     return []
 
 def andset(repo, subset, x, y):


More information about the Mercurial-devel mailing list