revset: speedup matching() by stopping the match early if a field does not match
authorAngel Ezquerra <angel.ezquerra@gmail.com>
Fri, 13 Apr 2012 13:46:49 +0200
changeset 16445 453c8670566c
parent 16444 432f198600c6
child 16446 984e0412e82b
revset: speedup matching() by stopping the match early if a field does not match Rather than getting all the fields that are being matches from every revision and then comparing them to those of the target revision, compare each field one by one and stop the match as soon as there is a match failure. This can greatly reduce the match time when matching multiple fields. The impact on match time when matching a single field seems negligible (according to my measurements).
mercurial/revset.py
--- a/mercurial/revset.py	Fri Apr 13 13:35:45 2012 +0200
+++ b/mercurial/revset.py	Fri Apr 13 13:46:49 2012 +0200
@@ -970,19 +970,22 @@
             raise error.ParseError(
                 _("unexpected field name passed to matching: %s") % info)
         getfieldfuncs.append(getfield)
-
     # convert the getfield array of functions into a "getinfo" function
     # which returns an array of field values (or a single value if there
     # is only one field to match)
-    if len(getfieldfuncs) == 1:
-        getinfo = getfieldfuncs[0]
-    else:
-        getinfo = lambda r: [f(r) for f in getfieldfuncs]
+    getinfo = lambda r: [f(r) for f in getfieldfuncs]
 
     matches = []
     for rev in revs:
         target = getinfo(rev)
-        matches += [r for r in subset if getinfo(r) == target]
+        for r in subset:
+            match = True
+            for n, f in enumerate(getfieldfuncs):
+                if target[n] != f(r):
+                    match = False
+                    break
+            if match:
+                matches.append(r)
     if len(revs) > 1:
         matches = sorted(set(matches))
     return matches